#include <sys_config.h>#include <osal/osal.h>
#include <basic_types.h>
#include <api/libc/alloc.h>
#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <hld/hld_dev.h>
#include <hld/dmx/dmx_dev.h>
#include <hld/dmx/dmx.h>
#include <api/libttx/lib_ttx.h>
#include <hld/hld_dev.h>
#include <hld/vbi/vbi.h>
#include <hld/vbi/vbi_dev.h>
#include <hld/osd/osddrv_dev.h>#define TTXDEC_PRINTF PRINTF
//#define TTXDEC_PRINTF libc_printf
#ifdef SEE_CPU
OSAL_ID TTX_SEM_ID = INVALID_ID;
#define ENTER_TTX_ENG() osal_semaphore_capture(TTX_SEM_ID,OSAL_WAIT_FOREVER_TIME)
#define LEAVE_TTX_ENG() osal_semaphore_release(TTX_SEM_ID)
#else
#define ENTER_TTX_ENG() 
#define LEAVE_TTX_ENG()
#endif
struct ttx_config_par g_ttx_pconfig_par;
UINT8 ttx_eng_state;
static struct PBF_CB * pCurRdCB;
/*static */UINT16 cur_page;
UINT8 transparent_level;
/*static*/ UINT16 WaitPage ; //..100 - 899
static UINT16 req_page; //..100 - 899
static UINT8 link_line_data[40];
static UINT16 page_queue[4];
static UINT8 queue_tag;
UINT8 transparent_value[TTX_TRANSPARENT_LEVEL];
static struct t_ttx_lang g_init_page[TTX_SUBT_LANG_NUM];
static struct t_ttx_lang g_subt_page[TTX_SUBT_LANG_NUM];
static UINT8 g_subt_page_num = 0;
static UINT8 screen_transparent_flag=0;
static UINT8 screen_transparent_flag2=0;
extern UINT8 *g_ttx_p26_nation;
static struct PBF_CB * g_SubPages[80];//store all subpages of one page
static UINT16 WaitSubPage;//0...79
static UINT16 cur_subpage;//0...79
static BOOL bUpdPage = FALSE;
static UINT8 status_line_data[40];//to show subpage status
static BOOL bFALSE = FALSE;//avoid a compiler bug
UINT8 *subpage_p26_nation = NULL;//to store subpage p26 naton map
static BOOL bUpd_subpage_p26 = FALSE;//flag when to use subpage_p26_nation
static BOOL new_history_mode = FALSE;//
static UINT8 seperate_ttxsubtitle_mode = 0;
static UINT8 mosaic_mode = 1;//1:continue mode,  0:separate mode
static UINT8 last_line_id;
static UINT8 g_current_language[3];
static UINT32 g_dsg_font_idx = 0xFFFFFFFF;//force ttx use font from special index for some special stream without lang info, cloud
//#define CALC_NATION_POS(subpage, line, i) ((subpage)*(25*20)+line*20+(i>>1))
//#define GET_SUBPAGE_NATION_MAP(subpage, line, i) ((subpage_p26_nation[CALC_NATION_POS(subpage, line, i)]>>((i&1)*4))&0xf)
extern UINT32 osd_ttx_width;//extern UINT32 osd_ttx_height;//extern UINT32 osd_ttx_startcol;//extern UINT32 osd_ttx_startrow; extern UINT32 osd_ttx_xoffset; extern UINT32 osd_ttx_yoffset; BOOL b_erase_ttx_auto = FALSE;void set_erase_ttx_auto(BOOL flag){    b_erase_ttx_auto = flag;}extern volatile BOOL ttx_show_on;#if 1//#ifdef TTX_FLASH_FUNCextern struct osd_device *osd_dev;extern UINT8 m_bCurRegion;static VSCR TTX_Flash_Vscr ;UINT8 ttx_flash_test_num = 0;static OSAL_ID ttx_flash_task_id = 0;UINT8 g_ttx_flash_buf[11264*2];//14*20*40*double_height=11200 extern UINT32 osd_ttx_height; extern UINT32 osd_ttx_startcol; extern UINT32 osd_ttx_startrow; ID ttx_flash_mutex = 0;static UINT32 last_temp_tick = 0;static UINT16 last_cur_subpage = 0xffff;static UINT16 last_cur_page =0xffff;typedef struct ttx_flash{       UINT32 left;    UINT32 top;    UINT32 width;    UINT32 height;    UINT8  fg_color;    UINT8 bg_color;    struct ttx_flash *next;}ttx_flash_node; ttx_flash_node *ttx_flash_list=NULL;void ttx_delete_whole(){    //libc_printf("%s(),line %d\n",__FUNCTION__,__LINE__);    ttx_flash_node *p;    MEMSET(g_ttx_flash_buf,0x00,11264*2);    osal_mutex_lock(ttx_flash_mutex, OSAL_WAIT_FOREVER_TIME);    while(ttx_flash_list)    {        p=ttx_flash_list;        ttx_flash_list=p->next;        free(p);    }     osal_mutex_unlock(ttx_flash_mutex);}static UINT8 ttx_front_color_change(UINT8 fg_color){    UINT8 ret =0 ;    switch(fg_color)    {        case TTX_B_BLACK:            ret = TTX_BC_BLACK;        break;        case TTX_B_RED:            ret = TTX_BC_RED;        break;        case TTX_B_GREEN:            ret = TTX_BC_GREEN;        break;        case TTX_B_YELLOW:            ret = TTX_BC_YELLOW;        break;        case TTX_B_BLUE:            ret = TTX_BC_BLUE;        break;        case TTX_B_MAGENTA:            ret = TTX_BC_MAGENTA;        break;        case TTX_B_CYAN:            ret = TTX_BC_CYAN;        break;        case TTX_B_WHITE:            ret = TTX_BC_WHITE;        break;    }    return ret;}int ttx_flsh_get_node(ttx_flash_node *pre, ttx_flash_node *node){    ttx_flash_node *ptr = ttx_flash_list;    int ret = 0;    if(ttx_flash_list == NULL || node == NULL || pre == NULL) return 0;    osal_mutex_lock(ttx_flash_mutex, OSAL_WAIT_FOREVER_TIME);    if(pre->height)    {        while(ptr)        {            if(ptr == pre->next)            {                memcpy(node, ptr, sizeof(ttx_flash_node));                ret = 1;                break;            }            ptr=ptr->next;        }        if(NULL == ptr)            ret = 0;    }    else    {        memcpy(node, ttx_flash_list, sizeof(ttx_flash_node));        ret = 1;    }    osal_mutex_unlock(ttx_flash_mutex);    return ret;}void ttx_flash_task(){        INT32 i =0;    struct OSDRect r;    UINT8 fc_color = 0;    ttx_flash_node p_node;    UINT32 u_left =0;    UINT32 u_top =0;    UINT32 u_width =0;    UINT32 u_height =0;    UINT8  fg_color =0;    UINT8  bg_color =0;    while(1)    {        MEMSET(&p_node, 0, sizeof(p_node));                while(ttx_flsh_get_node(&p_node, &p_node))        {            TTX_Flash_Vscr.vR.uLeft =  p_node.left;            TTX_Flash_Vscr.vR.uTop =  p_node.top;            TTX_Flash_Vscr.vR.uWidth =  p_node.width;            TTX_Flash_Vscr.vR.uHeight =  p_node.height;            TTX_Flash_Vscr.lpbScr = g_ttx_flash_buf;            r.uLeft =  p_node.left;            r.uTop =  p_node.top;            r.uWidth =  p_node.width;            r.uHeight =  p_node.height;            MEMSET(g_ttx_flash_buf,0x00,11264*2);            OSDDrv_RegionRead((HANDLE)osd_dev,m_bCurRegion,&TTX_Flash_Vscr,&r);            fc_color = ttx_front_color_change( p_node.bg_color);            for(i=0;i<TTX_Flash_Vscr.vR.uWidth*TTX_Flash_Vscr.vR.uHeight;++i)            {                if(g_ttx_flash_buf[i]<=TTX_F_WHITE)                {                                        g_ttx_flash_buf[i]= fc_color;                   }            }            OSDDrv_RegionWrite((HANDLE)osd_dev, m_bCurRegion, &TTX_Flash_Vscr, &r);         }        osal_task_sleep(500);        MEMSET(&p_node, 0, sizeof(p_node));        while(ttx_flsh_get_node(&p_node, &p_node))        {            TTX_Flash_Vscr.vR.uLeft = p_node.left;            TTX_Flash_Vscr.vR.uTop =  p_node.top;            TTX_Flash_Vscr.vR.uWidth =  p_node.width;            TTX_Flash_Vscr.vR.uHeight =  p_node.height;            TTX_Flash_Vscr.lpbScr = g_ttx_flash_buf;            r.uLeft =  p_node.left;            r.uTop =  p_node.top;            r.uWidth =  p_node.width;            r.uHeight =  p_node.height;            OSDDrv_RegionRead((HANDLE)osd_dev,m_bCurRegion,&TTX_Flash_Vscr,&r);            for(i=0;i<TTX_Flash_Vscr.vR.uWidth*TTX_Flash_Vscr.vR.uHeight;++i)            {                if(g_ttx_flash_buf[i]>= TTX_BC_BLACK)                    g_ttx_flash_buf[i]=  p_node.fg_color;            }            OSDDrv_RegionWrite((HANDLE)osd_dev, m_bCurRegion, &TTX_Flash_Vscr, &r);        }        osal_task_sleep(500);    }    }INT32 ttx_flash_task_creat()//(struct vbi_device *dev){		OSAL_T_CTSK t_ctsk;	t_ctsk.task = (FP)ttx_flash_task;	t_ctsk.para1 = 0;	t_ctsk.para2 = 0;	t_ctsk.stksz = 0x0C00;	t_ctsk.quantum = 10;    t_ctsk.itskpri = OSAL_PRI_NORMAL; #ifdef _TDS_INFO_MONITOR    t_ctsk.name[0] = 'T';//TTX    t_ctsk.name[1] = 'F';//FLASH    t_ctsk.name[2] = 'T';//TASK#endif	ttx_flash_task_id = osal_task_create(&t_ctsk);	if(OSAL_INVALID_ID==ttx_flash_task_id)	{	       // VBI_PRINTF("Can not create VBIDec_Task!!!\n");		 ASSERT(0);	}	return RET_SUCCESS;}#if 0     INT32 ttx_flash_task_delete()    {    	if(OSAL_E_OK!=osal_task_delete(ttx_flash_task_id))    	{    		while(1)    		{    		   // VBI_PRINTF("Delete ttx flash task of %s failed!\n");    		    osal_task_sleep(2000);    		}    	}    	if(OSAL_E_OK!=osal_flag_delete(ttx_flash_flag_id))    	{    		while(1)    		{    		    //VBI_PRINTF("Delete ttx flash flag of %s failed!\n");    		    osal_task_sleep(2000);    		}    	}    	/* clear vbi data when close*/    	return RET_SUCCESS;    }#endif#endifUINT32 get_subpage_nation_map(UINT16 subpage, UINT16 line, UINT16 i)
{//use this function to replace GET_SUBPAGE_NATION_MAP to avoid bug, cloud
    UINT32 pos;
    UINT32 ret;
    if(subpage>=80)
        return 0;
    pos = ((subpage)*(25*20)+line*20+(i>>1));
    ret = ((subpage_p26_nation[pos]>>((i&1)*4))&0xf);
    return ret;
}
void show_subpage_status();
void show_ttx_info();
void ttx_eng_set_seperate_ttxsubt_mode(struct vbi_device *ttx_dev, UINT8 mode)
{
    seperate_ttxsubtitle_mode = mode;
}
void ttx_eng_set_ttx_history_mode(struct vbi_device *ttx_dev, BOOL mode)
{
    new_history_mode = mode;
}
void ttx_eng_set_ttx_dsg_font(UINT32 idx)
{
	g_dsg_font_idx = idx;
}
void init_SubPageCB()
{	
	int i;
	for(i=0;i<80;i++)
	{    
        {
		g_SubPages[i] = (struct PBF_CB *)(g_ttx_pconfig_par.ttx_subpage_addr  + 1040*i);
		g_SubPages[i]->valid = 0x00;
		g_SubPages[i]->page_id = 0xffff;
        g_SubPages[i]->sub_page_id = 0xffff;//cloud
		g_SubPages[i]->buf_start = (UINT8*)(g_ttx_pconfig_par.ttx_subpage_addr  + 1040*i + 40);
		g_SubPages[i]->link_red = 0xffff;	
		g_SubPages[i]->link_green = 0xffff;	
		g_SubPages[i]->link_yellow = 0xffff;	
		g_SubPages[i]->link_cyan = 0xffff;	
		g_SubPages[i]->complement_line = 0;		
        }

		MEMSET(g_SubPages[i]->buf_start, 0x20, 1000);
	}
    //LIBC_PRINTF("finish of init_SubPageCB\n");
    //MEMSET(empty_line, 0x20, 40);
	return ;
}
void clear_SubPageCB()
{
    int i;
	for(i=0;i<80;i++)
	{   
		if(g_SubPages[i]->valid ==1)
		{
            MEMSET(g_SubPages[i]->buf_start, 0x20, 1000);
            g_SubPages[i]->valid =0;
		}
	}
    //LIBC_PRINTF("finish of clear_SubPageCB\n");
	return ;
}
INT32 set_SubPageCB(UINT16 sub_page_id, struct PBF_CB *cb, UINT8 start_line_num, UINT8 end_line_num, BOOL show_status)
{
    if(sub_page_id>79 || cb->valid==0)
        return 0;
    if(start_line_num>end_line_num)
        return 0;
    g_SubPages[sub_page_id]->page_id = cb->page_id;
    g_SubPages[sub_page_id]->sub_page_id = cb->sub_page_id;    
	g_SubPages[sub_page_id]->link_red = cb->link_red;	
    g_SubPages[sub_page_id]->link_green = cb->link_green;	
    g_SubPages[sub_page_id]->link_yellow = cb->link_yellow;	
	g_SubPages[sub_page_id]->link_cyan = cb->link_cyan;	
    g_SubPages[sub_page_id]->link_next = cb->link_next;	
    g_SubPages[sub_page_id]->link_index = cb->link_index;
    g_SubPages[sub_page_id]->ErasePage = cb->ErasePage;
    g_SubPages[sub_page_id]->Newsflash = cb->Newsflash;
    g_SubPages[sub_page_id]->Subtitle = cb->Subtitle;
    g_SubPages[sub_page_id]->SuppressHeader = cb->SuppressHeader;
    g_SubPages[sub_page_id]->UpdateIndicator = cb->UpdateIndicator;
    g_SubPages[sub_page_id]->InterruptedSequence = cb->InterruptedSequence;
    g_SubPages[sub_page_id]->InhibitDisplay = cb->InhibitDisplay;
    g_SubPages[sub_page_id]->MagazineSerial = cb->MagazineSerial;
    g_SubPages[sub_page_id]->NationOption = cb->NationOption;
    g_SubPages[sub_page_id]->G0_set = cb->G0_set;
    g_SubPages[sub_page_id]->Second_G0_set = cb->Second_G0_set;
    g_SubPages[sub_page_id]->pack24_exist = cb->pack24_exist;
    g_SubPages[sub_page_id]->complement_line =cb->complement_line;
    MEMSET(g_SubPages[sub_page_id]->buf_start+start_line_num*40, 0x20, (end_line_num-start_line_num+1)*40);//cloud
    MEMCPY(g_SubPages[sub_page_id]->buf_start+start_line_num*40, cb->buf_start+start_line_num*40, (end_line_num-start_line_num+1)*40);//cloud
    //MEMSET(g_SubPages[sub_page_id]->buf_start+line_num*40, 0x20, 40);//cloud    //MEMCPY(g_SubPages[sub_page_id]->buf_start+line_num*40, cb->buf_start+line_num*40, 40);
    if(g_ttx_pconfig_par.parse_packet26_enable == TRUE)
    {
        //MEMCPY(subpage_p26_nation+(cb->sub_page_id)*(25*20)+line_num*20, g_ttx_p26_nation+((cb->page_id)-100)*(25*20)+line_num*20, 20);//cloud
        MEMCPY(subpage_p26_nation+(cb->sub_page_id)*(25*20)+start_line_num*20, g_ttx_p26_nation+((cb->page_id)-100)*(25*20)+start_line_num*20, (end_line_num-start_line_num+1)*20);//cloud
    }
    if(end_line_num!=0)
        g_SubPages[sub_page_id]->valid = cb->valid;
    if((cb->Subtitle==0) && show_status)
       show_subpage_status();
    return 1;
}
INT32 ttx_request_sub_page_up(UINT16 page_id , UINT16 sub_page_id, struct PBF_CB ** cb )
{
    if(page_id<100 || page_id>899)
        return RET_FAILURE;
    if(sub_page_id>=79)
        return RET_FAILURE;
    while(sub_page_id < 79)
    {
        sub_page_id++;
        if(g_SubPages[sub_page_id]->valid==1 
           && g_SubPages[sub_page_id]->page_id == page_id)
        {    
            *cb=g_SubPages[sub_page_id];
	        return RET_SUCCESS;
        }       
    }
    return RET_FAILURE;
}
INT32 ttx_request_sub_page_down(UINT16 page_id , UINT16 sub_page_id, struct PBF_CB ** cb )
{ 
    if(page_id<100 || page_id>899)
        return RET_FAILURE;
    if(sub_page_id>79)
        return RET_FAILURE;
	while(sub_page_id <=79 && sub_page_id >0)
    {
        sub_page_id--;
        if(g_SubPages[sub_page_id]->valid==1 
           && g_SubPages[sub_page_id]->page_id == page_id)
        {    
            *cb=g_SubPages[sub_page_id];
	        return RET_SUCCESS;
        }       
    }
    if(sub_page_id==0)
    {
        sub_page_id=cur_subpage;
        cur_subpage=0;
        show_subpage_status();
        cur_subpage=sub_page_id;
    }
    return RET_FAILURE;
}
void show_subpage_status()
{
    UINT8 j,i;
	UINT8 *data ;
    UINT8 max_subpage=0;
    UINT8 show_page=0;
	UINT8 char_set;
	UINT8 alpha_mosiac ;
	UINT8 fg_color ;
	UINT8 pre_bg_color;
	UINT8 bg_color ;
	UINT8 width ;
	UINT8 height ;
	UINT8 conceal ;
	UINT8 continous ;
	UINT8 hold_mosiac;
	UINT8 real_alpha_mosiac ;
	UINT8 real_mosiac;
	UINT8 last_mosiac;
	UINT8 real_fg_color;
	UINT8 real_bg_color;
	UINT8 real_width;
	UINT8 real_height;
	UINT8 alpha=0x01;
	UINT8 mosiac=0xb0;
	real_alpha_mosiac = alpha_mosiac = 1;
	real_fg_color = fg_color = TTX_F_WHITE;
	pre_bg_color = TTX_B_WHITE;
	real_bg_color = bg_color = TTX_B_BLACK;
	real_width = width = 0;
	real_height = height = 0;
	conceal = 0;
	continous = 1;
	hold_mosiac = 0;
	real_mosiac =0x20;
	last_mosiac =0x20;
	data = status_line_data;
    if(cur_page == 0xffff || cur_subpage == 0xffff)
        return;
    for(j=79;j>0;j--)
    {
      if(g_SubPages[j]->page_id==cur_page && g_SubPages[j]->valid==1)
        {
            max_subpage=j;
            j=1;
        }
    }
	MEMSET(status_line_data,0x20,40);
    if(g_SubPages[max_subpage]->Subtitle==1)//|| g_SubPages[max_subpage]->Newsflash==1)//not show subpage status when have subtitle
    {
		return;	//subtitle no subpage status!
//        goto showline;
    }
       //LIBC_PRINTF("cur_subpage=%d,cur_page=%d,max_subpage=%d\n",cur_subpage,cur_page,max_subpage);
    show_page = cur_subpage/11;
    j=show_page*11;  
    if(cur_subpage>10)
    {
        status_line_data[0] = 0x2D;
        status_line_data[1] = 0x29;
    }
    if(max_subpage/11>cur_subpage/11)
    {
        status_line_data[37] = TTX_F_WHITE;
        status_line_data[38] = 0x28;
        status_line_data[39] = 0x2B;
    }  
	for(i=0;(j<show_page*11+11)&&(j<=max_subpage);j++,i++)
	{
        if(show_page==0)
        {
            if(0==cur_subpage)
                status_line_data[2] = TTX_F_RED;
            else
                status_line_data[2] = TTX_F_WHITE;            if(FALSE == b_erase_ttx_auto)            {
            status_line_data[3] = 0x41;
            status_line_data[4] = 0x55;
            status_line_data[5] = 0x54;
            status_line_data[6] = 0x4F;            }            else            {                status_line_data[3] = 0x20;                status_line_data[4] = 0x20;                status_line_data[5] = 0x20;                status_line_data[6] = 0x20;            }   
	        if(j!=0)
		    {
                if(j==cur_subpage)
                    status_line_data[4+i*3] = TTX_F_RED;
                else if(g_SubPages[j]->page_id==cur_page && g_SubPages[j]->valid==1)
                    status_line_data[4+i*3] = TTX_F_WHITE;
                else
                    status_line_data[4+i*3] = TTX_F_BLACK;
		        status_line_data[5+i*3] = (UINT8)(j/10) + 0x30;
		        status_line_data[6+i*3] = (UINT8)(j%10) + 0x30;
		    } 
        }
        else
        {
                if(j==cur_subpage)
                    status_line_data[2+i*3] = TTX_F_RED;
                else if(g_SubPages[j]->page_id==cur_page && g_SubPages[j]->valid==1)
                    status_line_data[2+i*3] = TTX_F_WHITE;
                else
                    status_line_data[2+i*3] = TTX_F_BLACK;
		        status_line_data[3+i*3] = (UINT8)(j/10) + 0x30;
		        status_line_data[4+i*3] = (UINT8)(j%10) + 0x30;
        
        }
	}
showline:	
	for(j=0;j<40;j++,data++)
	{
		if (*data < 0x20)
		{
			if(hold_mosiac == 0)
				real_mosiac = 0x20;
			else
				real_mosiac = last_mosiac;
			switch(*data)
			{
				case 0x00:
				case 0x01:
				case 0x02:
				case 0x03:
				case 0x04:
				case 0x05:
				case 0x06:
				case 0x07:
					alpha_mosiac = 1;
					fg_color = *data;
					pre_bg_color = fg_color+8;
					if(real_alpha_mosiac == 1)//alpha
						real_mosiac = 0x20;
					break;
				case 0x0c:
					break;
				case 0x0d:
					break;
				case 0x0e:
					break;
				case 0x0f:
					break;
				case 0x10:
				case 0x11:
				case 0x12:
				case 0x13:
				case 0x14:
				case 0x15:
				case 0x16:
				case 0x17:
					alpha_mosiac = 0;
					fg_color = *data - 0x10;
					pre_bg_color = fg_color+8;
					break;
				case 0x18:
					conceal = 1;
					break;
				case 0x19:
					continous = 0x01;
					break;
				case 0x1a:
					continous = 0x00;
					break;
				case 0x1b:
					break;
				case 0x1c:
					bg_color = TTX_B_BLACK;
					real_bg_color =bg_color;
					break;
				case 0x1d:
					bg_color = pre_bg_color;
					real_bg_color =bg_color;
					break;
				case 0x1e:
					hold_mosiac = 1;
					real_mosiac = last_mosiac;
					break;
				case 0x1f:
					hold_mosiac = 0;
					break;
				default :
					break;
			}
			if(real_alpha_mosiac == 0)
				g_ttx_pconfig_par.ttx_drawchar(j*TTX_CHAR_W, 25*TTX_CHAR_H, mosiac, real_fg_color, real_bg_color, real_width, real_height, real_mosiac, 0);
			else
				g_ttx_pconfig_par.ttx_drawchar(j*TTX_CHAR_W, 25*TTX_CHAR_H, mosiac, real_fg_color, real_bg_color, real_width, real_height, 0x20, 0);
		}
		else if (*data >= 0x20 && *data < 0x80)
		{
			if(alpha_mosiac == 1)
			{
				char_set = alpha;
			}			else
			{
				char_set = mosiac;
				last_mosiac = *data;
			}
			g_ttx_pconfig_par.ttx_drawchar(j*TTX_CHAR_W, 25*TTX_CHAR_H, char_set, real_fg_color, real_bg_color, real_width, real_height, *data, 0);
		}
		real_alpha_mosiac = alpha_mosiac;
		real_fg_color = fg_color;
		real_bg_color =bg_color;
		real_width =width;
		real_height =height;
	}
    last_cur_subpage = cur_subpage;    //LIBC_PRINTF("show_subpage_status!!\n");
}
UINT8 key2char(TTX_KEYTYPE key)
{
	switch(key)
	{
		case TTX_KEY_NUM0 :	return 0x30;
		case TTX_KEY_NUM1 :	return 0x31;
		case TTX_KEY_NUM2 :	return 0x32;
		case TTX_KEY_NUM3 :	return 0x33;		case TTX_KEY_NUM4 :	return 0x34;
		case TTX_KEY_NUM5 :	return 0x35;
		case TTX_KEY_NUM6 :	return 0x36;
		case TTX_KEY_NUM7 :	return 0x37;
		case TTX_KEY_NUM8 :	return 0x38;
		case TTX_KEY_NUM9 :	return 0x39;
		default : return 0x00;
	}
}
static UINT8 _language_from_iso639(UINT8* language, UINT8 nation)
{
    //LIBC_PRINTF("g_current_language=%s,nation=%d\n",g_current_language,nation);
	if(MEMCMP(language,"cze",3)==0
        ||MEMCMP(language,"CZE",3)==0
		||MEMCMP(language,"ces",3)==0
		||MEMCMP(language,"CES",3)==0
		||MEMCMP(language,"slk",3)==0
		||MEMCMP(language,"SLK",3)==0
		||MEMCMP(language,"slo",3)==0
		||MEMCMP(language,"SLO",3)==0)
		return 0;
	//else if(MEMCMP(language,"ENG",3)==0)
        //||MEMCMP(language,"eng",3)==0)
	//	return 1;
	else if(MEMCMP(language,"est",3)==0
        ||MEMCMP(language,"EST",3)==0)
		return 2;
	else if(MEMCMP(language,"fre",3)==0
        ||MEMCMP(language,"FRE",3)==0
		||MEMCMP(language,"fra",3)==0
		||MEMCMP(language,"FRA",3)==0)
		return 3;	
	else if(MEMCMP(language,"ger",3)==0
        ||MEMCMP(language,"GER",3)==0
		||MEMCMP(language,"deu",3)==0
		||MEMCMP(language,"DEU",3)==0)
		return 4;
	else if(MEMCMP(language,"ita",3)==0
        ||MEMCMP(language,"ITA",3)==0)
		return 5;
	else if(MEMCMP(language,"lit",3)==0
        ||MEMCMP(language,"LIT",3)==0)
		return 6;
	else if(MEMCMP(language,"pol",3)==0
        ||MEMCMP(language,"POL",3)==0)
		return 7;
	else if(MEMCMP(language,"por",3)==0
        ||MEMCMP(language,"POR",3)==0
		||MEMCMP(language,"spa",3)==0
		||MEMCMP(language,"SPA",3)==0
		||MEMCMP(language,"esl",3)==0
		||MEMCMP(language,"ESL",3)==0
		||MEMCMP(language,"cat",3)==0
		||MEMCMP(language,"CAT",3)==0)
		return 8;
	else if(MEMCMP(language,"rum",3)==0
        ||MEMCMP(language,"RUM",3)==0
		||MEMCMP(language,"ron",3)==0
		||MEMCMP(language,"RON",3)==0)
		return 9;
	else if(MEMCMP(language,"slv",3)==0
		||MEMCMP(language,"scc",3)==0
		||MEMCMP(language,"srp",3)==0
		||MEMCMP(language,"scr",3)==0
		||MEMCMP(language,"hrv",3)==0)
		return 10;
	else if(MEMCMP(language,"swe",3)==0
        ||MEMCMP(language,"SWE",3)==0
		||MEMCMP(language,"sve",3)==0
		||MEMCMP(language,"SVE",3)==0
		||MEMCMP(language,"fin",3)==0
		||MEMCMP(language,"FIN",3)==0
		||MEMCMP(language,"hun",3)==0
		||MEMCMP(language,"HUN",3)==0
		||MEMCMP(language,"dan",3)==0
		||MEMCMP(language,"DAN",3)==0
		||MEMCMP(language,"nor",3)==0
		||MEMCMP(language,"dut",3)==0)
		return 11;
	else if(MEMCMP(language,"tur",3)==0
        ||MEMCMP(language,"TUR",3)==0)
		return 12;
	else if(MEMCMP(language,"rus",3)==0
        ||MEMCMP(language,"RUS",3)==0
		||MEMCMP(language,"bul",3)==0
		||MEMCMP(language,"BUL",3)==0)
		return 0x20;
	else if(MEMCMP(language,"ukr",3)==0
        ||MEMCMP(language,"UKR",3)==0)
		return 0x30;
	else if(MEMCMP(language,"grc",3)==0
        ||MEMCMP(language,"GRC",3)==0
		||MEMCMP(language,"gre",3)==0
		||MEMCMP(language,"GRE",3)==0
		||MEMCMP(language,"ell",3)==0
		||MEMCMP(language,"ELL",3)==0)
		return 0x40;	
	else if(MEMCMP(language,"ara",3)==0
        ||MEMCMP(language,"ARA",3)==0)
		return 0x50;		
	else if(MEMCMP(language,"heb",3)==0
        ||MEMCMP(language,"HEB",3)==0)
		return 0x60;			
	else
	{
		//LIBTTX_PRINTF("_language_from_iso639: current language -> %c%c%c\n",language[0],language[1],language[2]);
		//return default alpha
		switch (nation)
		{
			case 0: return 1;	//English
			case 1: return 4;	//German
			case 2: return 11;	//Swedish/Finnish/Hungarian
			case 3: return 5;	//Italian
			case 4: return 3;	//French
			case 5: return 8;	//Portuguese/Spanish
			case 6: return 0;	//Czech/Slovak
			case 7:
				if(g_dsg_font_idx == LATIN_ARABIC)
					return 0x50;	//Arabic
				else if(g_dsg_font_idx == LATIN_GREEK)
					return 0x40;	//Greek
				else
					return 9;	//Rumanian
			default: return 1;	//English
		}
	}
}
static UINT8 language_from_iso639(UINT8 nation)
{	int i;
	//for ttx_subtitle, need check its own language
	if (pCurRdCB != NULL && pCurRdCB->Subtitle)
	{
		for (i=0; i<g_subt_page_num; i++)
		{
			if (g_subt_page[i].page == cur_page)
				return _language_from_iso639(g_subt_page[i].lang, nation);
		}
	}
	return _language_from_iso639(g_current_language, nation);
}
static void language_select(UINT8 g0_set,UINT8 nation,UINT8 *alpha)
{   
    //libc_printf("g0_set=%d,nation=%d,g_current_language=%s\n",g0_set,nation,g_current_language);
	switch(nation)
	{
	case 0:
		if(g0_set==0||g0_set==2||g0_set==8)
			*alpha = 1;		//English		
		else if(g0_set==1)	//Polish
			*alpha = 7;		
		else if(g0_set==4)	//[Cyrillic-1:Serbian/Croatian]
			*alpha = 0x10;
		else
			*alpha = language_from_iso639(nation);
		break;	
	case 1:
		if(g0_set==0||g0_set==1||g0_set==2||g0_set==4)
			*alpha = 4;		//German
		else
			*alpha = language_from_iso639(nation);
		break;
	case 2:
		if((MEMCMP(g_current_language,"dan",3) == 0) || (MEMCMP(g_current_language,"DAN",3) == 0))//xuehui_ttx		{			//libc_printf("dan \n");			*alpha = 13;	//Danish			break;		}		if(g0_set==0||g0_set==1||g0_set==2)
			*alpha = 11;		//Swedish/Finnish/Hungarian	
		if(g0_set==4)	
			*alpha = 2;		//Estonian	
		else 
			*alpha = language_from_iso639(nation);
		break;	
	case 3:
		if((MEMCMP(g_current_language,"lit",3) == 0) || (MEMCMP(g_current_language,"LIT",3) == 0))
		{
			*alpha = 6;	//Lettish/Lithuanian
			break;
		}

		if(g0_set==0||g0_set==1||g0_set==2)
			*alpha = 5;		//Italian
		else if(g0_set==4)	
			*alpha = 6;		//Lettish/Lithuanian
		else 
			*alpha = language_from_iso639(nation);
		break;	
	case 4:
		if(g0_set==0||g0_set==1||g0_set==2||g0_set==8)
			*alpha = 3;		//French
		else if(g0_set==4)	
			*alpha = 0x20;	//[Cyrillic-2:Russian/Bulgarian]	
		else 
			*alpha = language_from_iso639(nation);
		break;	
	case 5:
		if(g0_set==0||g0_set==2)
			*alpha = 8;		//Portuguese/Spanish
		else if(g0_set==3)	
			*alpha = 0x0A;	//Serbian/Croatian/Slovenian	
		else if(g0_set==4)
			*alpha = 0x30;	//[Cyrillic-3:Ukrainian]		
		else if(g0_set==0xA)
			*alpha = 0x60;	//[Hebrew]			
		else 
			*alpha = language_from_iso639(nation);
		break;	
	case 6:
		if(g0_set==0||g0_set==1||g0_set==4)
			*alpha = 0;		//Czech/Slovak		
		else if(g0_set==2 || g0_set==6)	
			*alpha = 12;		//Turkish
		else 
		{   
            if((MEMCMP(g_current_language,"xxx",3) == 0)&&(g_ttx_pconfig_par.no_ttx_descriptor==TRUE))
              *alpha = 0;//Czech/Slovak
            else
			  *alpha = language_from_iso639(nation);
		}
		break;			
	case 7:
		if(g0_set==3)	
			*alpha = 9;		//Rumanian	
		else if(g0_set==6)	
			*alpha = 0x40;	//[Greek]	
		else if(g0_set==0x8 || g0_set==0xA)	
			*alpha = 0x50;	//[Arabic]			
		else 
		{
            if((MEMCMP(g_current_language,"xxx",3) == 0)&&(g_ttx_pconfig_par.no_ttx_descriptor==TRUE))
            {
            	if(g_dsg_font_idx == LATIN_ARABIC)
              		*alpha = 0x50;	//[Arabic]
              	else
              		*alpha = 0x40;//[Greek]
            }
            else
				*alpha = language_from_iso639(nation);		
		}
		break;	
	default :
		*alpha = language_from_iso639(nation);	
		break;
	}
	//libc_printf("language_select: alpha = 0x%X\n",*alpha);
	return;
}
static UINT8 g2_language_from_iso639(UINT8 nation)
{
	UINT8 lan = language_from_iso639(nation);
	if(lan < 0x10)
		lan = 0;
	else if(lan == 0x10 || lan == 0x20 || lan == 0x30)
		lan = 0x10;
	else if(lan == 0x40)
		lan = 0x20;
	else if(lan == 0x50)
		lan = 0x30;
	else if(lan == 0x60)
		lan = 0x40;
	else
		lan = 0;
	return lan;
}
static void language_select_g2(UINT8 g0_set,UINT8 nation,UINT8 *alpha)
{   
	*alpha = 0;
	switch(g0_set)
	{
	case 0:
	case 2:
		if(nation == 7)
			*alpha = g2_language_from_iso639(nation);
		else
			*alpha = 0;
		break;
	case 1:
		if(nation == 5 || nation == 7)
			*alpha = g2_language_from_iso639(nation);
		else
			*alpha = 0;
		break;
	case 3:
		if(nation == 5 || nation == 7)
			*alpha = 0;
		else
			*alpha = g2_language_from_iso639(nation);
		break;
	case 6:
		if(nation==6)
			*alpha = 0;
		else if(nation==7)
			*alpha = 0x20;//Greek G2
		else
			*alpha = g2_language_from_iso639(nation);
		break;
	case 4:
		if(nation==1||nation==2||nation==3||nation==6)
			*alpha = 0;
		else if(nation==0||nation==4||nation==5)
			*alpha = 0x10;//Cyrillic G2
		else
			*alpha = g2_language_from_iso639(nation);
		break;
	case 8:
		*alpha = 0x30;//Arabic G2
		break;
	case 10:
		if(nation==5||nation==7)
			*alpha = 0x30;
		break;
	default:
		*alpha = g2_language_from_iso639(nation);
		break;
	}
	return;
}//check if has displayable character
//for "0x0b x x x 0x0a", if has no displayable character between 0x0b and 0x0a, do not show anything
static BOOL check_displayable_char(UINT8* data, UINT8 len)
{
	int i;
	for (i=0; i<len; i++)
		if (data[i] > 0x20 && data[i] < 0x80)
			return TRUE;
	return FALSE;
}
UINT8 get_mosaic_mode()
{
    return mosaic_mode;
}
extern UINT8 g_packet_exist[8][25];
//#define PRINTF_PAGE_PACKET
#ifdef PRINTF_PAGE_PACKET
static UINT16 draw_page_id = 0xffff; //page id
static UINT8 draw_page_line = 0xff;//page line
static UINT8 draw_page_col = 0xff;//page col
#endif
UINT8 last_draw_data[24][40];//line1 - line24, not include line 0
BOOL ttxsubt_double_line_show = FALSE;
//extern BOOL page_erase;
 static BOOL b_useful_data  = FALSE; static UINT32 end_page_line_num = 24; static UINT32 end_line_of_the_page = 0;  void ttx_subt_timer_start(void);  void parse_line(struct PBF_CB * cb, UINT8 line_num,UINT8 skip_start8byte,UINT8 skip_end8byte)
{
	UINT8 j,i,mag;
	UINT8 draw_next_line = 0;
	UINT8 start_byte,end_byte;
	UINT8 *data ;
	UINT8 tempdata;	UINT8 double_line  = 0;	UINT16 char_set;
	UINT8 alpha_mosiac ;
	UINT8 fg_color ;
	UINT8 pre_bg_color;
	UINT8 bg_color ;
	UINT8 width ;
	UINT8 height ;
	UINT8 conceal ;
	UINT8 continous ;
	UINT8 hold_mosiac;
	UINT8 real_alpha_mosiac ;
	UINT8 real_mosiac;
	UINT8 last_mosiac;
	UINT8 real_fg_color;
	UINT8 real_bg_color;
	UINT8 real_width;
	UINT8 real_height;
	UINT16 alpha = 1,alpha1=0, alpha2=0;
	UINT8  alpha1_g1=0, alpha2_g1=0, alpha_g2=0;
	UINT16 mosiac=0xb0;	UINT8 box_display = 0;
	UINT8 box_start = 0;
	UINT8 display_enable = 1;
	UINT8 double_width_hold = 0;
	UINT8 prev_data = 0x20;
	UINT8 p26_char_set =0;
	UINT8 clear_extra_data = 0;    UINT8 ttx_flash_flag =0;//whether have ttx end flag 0x09    UINT8 ttx_flash_start_column = 0;    //UINT32 ttx_flash_tick_test = 0;    UINT32 u_left = 0;    UINT32 u_top = 0;    UINT32 u_height = 0;    ttx_flash_node *p_node= NULL;     #if 0     if(!cb)     {	        SDBBP();     }	     #endif         if(cb->page_id/100==8)
		mag=0;
	 else
		mag=cb->page_id/100;
	/*if(line_num>0 && line_num < 25)//line 1 - line 24 need compare, for fix bug
	{
		if( MEMCMP(last_draw_data[line_num-1], (cb->buf_start+(40*line_num)), 40) )
			MEMCPY(last_draw_data[line_num-1], (cb->buf_start+(40*line_num)), 40);
		else
		{
			if(MEMCMP(last_draw_data[line_num-1], blank, 40))
				return;//if equal to blank line, still need to draw it, to refresh exist line
		}
	}    */		//libc_printf("cb->G0_set=%d,cb->NationOption=%d,cb->Second_G0_set=%d\n",
	//              cb->G0_set,cb->NationOption,cb->Second_G0_set);
	language_select(cb->G0_set>>3,cb->NationOption,&alpha1_g1);
	language_select(cb->Second_G0_set>>3,cb->Second_G0_set&7,&alpha2_g1);
	//language_select_g2(cb->G0_set>>3, cb->G0_set&0x3, &alpha_g2);
	language_select_g2(cb->G0_set>>3, cb->NationOption, &alpha_g2);		//LIBC_PRINTF("alpha1=%d,alpha2=%d\n",alpha1,alpha2);
	alpha1 = alpha1_g1 | (alpha_g2<<8);
	alpha2 = alpha2_g1 | (alpha_g2<<8);

	alpha = alpha1;
	if(line_num != 0 && cb->InhibitDisplay == 1)
		return;
	if((1<<line_num)&cb->complement_line)
		return;
	cb->complement_line &= ~(1<<(line_num+1));
LineStart:	
	real_alpha_mosiac = alpha_mosiac = 1;
	real_fg_color = fg_color = TTX_F_WHITE;
	pre_bg_color = TTX_B_WHITE;
	real_bg_color = bg_color = TTX_B_BLACK;
	real_width = width = 0;
	real_height = height = 0;
	conceal = 0;
	continous = 1;
	hold_mosiac = 0;
	real_mosiac =0x20;
	last_mosiac =0x20;
	if(double_line == 1 && line_num == 24)
	{
		double_line = 0;
		return;
	}
	if(skip_start8byte == 1)
	{
		start_byte = 8;
		data = cb->buf_start + (40*line_num) +8;
	}
	else
	{
		start_byte = 0;
		data = cb->buf_start + (40*line_num);
	}
	if(skip_end8byte == 1)
	{
		end_byte = 32;
	}
	else
	{
		end_byte = 40;
	}
	for(i=0;i<g_subt_page_num;i++)//some stream have wrong header, force it to 1 ,cloud
	{
		if((g_subt_page[i].page == cb->page_id) && (cb->Subtitle!=1) && (g_subt_page[i].page!=g_init_page[i].page))
			cb->Subtitle=1;
	}
	if(cb->Subtitle||cb->Newsflash)
	{
		if(seperate_ttxsubtitle_mode == 0 || (get_ttxmenu_status()== FALSE))
		{
			box_display = 1;
			box_start = 0;
			if(line_num == 0)
			{  
                 if(/*cb->SuppressHeader==1 &&*/ cb->InterruptedSequence==1 && 
					((cb->ErasePage==0 && cb->MagazineSerial==1) || (cb->ErasePage==1 && cb->MagazineSerial==0)))
				{//cloud,some streams transfer ttx-subtitle part by part like mutiplex c32_001.ts
				}
				else
					screen_transparent_flag = 0;
				return;
			}
			if(screen_transparent_flag == 0 /*|| page_erase == TRUE*/)
			{
				if(g_ttx_pconfig_par.ttx_color_number==16 )
				{
					TTX_SetBackAlpha(transparent_value[TTX_TRANSPARENT_LEVEL-1]);
					if(cb->MagazineSerial==0 && cb->Subtitle==1 && cb->SuppressHeader==1 && cb->ErasePage==0)
					{ //only clear the line which have no data to avoid refresh too quickly               
						for(i=1,j=0;i<24;i++)
						{
							if(g_packet_exist[mag][i]==1)
							{
								if(j==0)
								{
									TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset,osd_ttx_width,i*TTX_CHAR_H,TTX_B_BLACK);//(0,i-1);
								}
								else
								{
									if(i-j>2)
										TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset+(j+2)*TTX_CHAR_H,osd_ttx_width,(i-j-2)*TTX_CHAR_H,TTX_B_BLACK);//(j+2,i-1);
								}
								j=i;
							}
						}
						if(i==24 && j<23)
						{
							if(j!=0)
								TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset+(j+2)*TTX_CHAR_H,osd_ttx_width,(24-j-2)*TTX_CHAR_H,TTX_B_BLACK);//(j+2,24);
							else
								TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset,osd_ttx_width,25*TTX_CHAR_H,TTX_B_BLACK);//(0,24);
							TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset+24*TTX_CHAR_H,osd_ttx_width,TTX_CHAR_H,TTX_B_BLACK);//line24;
							if(g_ttx_pconfig_par.ttx_sub_page == TRUE)
								TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset+25*TTX_CHAR_H,osd_ttx_width,TTX_CHAR_H,TTX_B_BLACK);//line25;
						}
					}
					else
						TTX_SetScreenColor(TTX_B_BLACK);         
				}
				//if(g_ttx_pconfig_par.ttx_color_number==256)
				//TTX_SetScreenColor(TTX_TRANSPARENT);				//Ryan
				if(g_ttx_pconfig_par.ttx_color_number==256)
				{
					//TTX_SetScreenColor(TTX_TRANSPARENT);
					if((/*cb->MagazineSerial==0 && */cb->Subtitle==1/* && cb->SuppressHeader==1) && 
						((cb->ErasePage==0)*/ ))										{ //only clear the line which have no data to avoid refresh too quickly               
						for(i=1,j=0;i<24;i++)
						{
							if(g_packet_exist[mag][i]==1)
							{
								if(j==0)
								{
									TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset,osd_ttx_width,i*TTX_CHAR_H,TTX_TRANSPARENT);//(0,i-1);
								}
								else
								{
									if(i-j>2)
										TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset+(j+2)*TTX_CHAR_H,osd_ttx_width,(i-j-2)*TTX_CHAR_H,TTX_TRANSPARENT);//(j+2,i-1);
								}								j=i;
							}
						}
						if(i==24 && j<23)
						{
							if(j!=0)
								TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset+(j+2)*TTX_CHAR_H,osd_ttx_width,(24-j-2)*TTX_CHAR_H,TTX_TRANSPARENT);//(j+2,24);
							else
								TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset,osd_ttx_width,25*TTX_CHAR_H,TTX_TRANSPARENT);//(0,24);
							TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset+24*TTX_CHAR_H,osd_ttx_width,TTX_CHAR_H,TTX_TRANSPARENT);//line24;
							if(g_ttx_pconfig_par.ttx_sub_page == TRUE)
								TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset+25*TTX_CHAR_H,osd_ttx_width,TTX_CHAR_H,TTX_TRANSPARENT);//line25;
						}
					}
					else
					{
						TTX_SetScreenColor(TTX_TRANSPARENT);
					}
				}
				screen_transparent_flag = 1;
              //  page_erase = FALSE;
				screen_transparent_flag2 = 1;
			} 
		}
	}
	else
	{
		box_display = 0;
		if(screen_transparent_flag2 == 1)
		{
			if(g_ttx_pconfig_par.ttx_color_number==16)
				TTX_SetBackAlpha(transparent_value[transparent_level]);
			if(g_ttx_pconfig_par.ttx_color_number==256)
			{
				TTX_SetScreenColor(TTX_B_BLACK);
			}
			screen_transparent_flag2 = 0;
		}
	}
	if(get_ttxmenu_status()== TRUE && get_ttxinfo_status() == TRUE)
	{
		if(line_num ==24)
		{
			TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset+26*TTX_CHAR_H,16,TTX_CHAR_H,TTX_TRANSPARENT);
			TTX_ClearScreen(osd_ttx_xoffset+TTX_CHAR_W*39,osd_ttx_yoffset+26*TTX_CHAR_H,32,TTX_CHAR_H,TTX_TRANSPARENT);//clear extra blank
		}
		show_ttx_info();
	}    
show_pageheader:
	if((g_ttx_pconfig_par.ttx_sub_page == TRUE) &&bUpdPage == TRUE && skip_end8byte == 0 && line_num == 0)
	{//only update time with style
		start_byte=31;
		if(skip_start8byte==1)
			data += 23;
		else
			data += 31;
		while(*(data-1)<0x20)
		{
			data--;
			start_byte--;
		}     
	}
	if((cb->Subtitle ==1) && (seperate_ttxsubtitle_mode == 1) && (get_ttxmenu_status()== TRUE))   
	{
		if(line_num!=0)
			TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset,osd_ttx_width,26*TTX_CHAR_H,TTX_B_BLACK);//(0,25);
		return;
	}
	if(line_num==24 && cb->pack24_exist==1)
	{//cloud, if packet24 only have some no useful data, erase it
		j=0;
		for(i=0;i<40;i++)
		{
			if(*(data+i)>0x20)
				j++;
		}
		//if(j<8)
		//	MEMSET(data,0x20,40);
	}
   // libc_printf("%s,%d,start_byte %d,end_byte %d\n",__FUNCTION__,__LINE__,start_byte,end_byte);    if(1 == cb->Subtitle && line_num<=end_page_line_num)    {        b_useful_data = check_displayable_char(data,40);        if(b_useful_data)        {          //  libc_printf("%s,%d,b_useful_data %d,line_num %d\n",__FUNCTION__,__LINE__,b_useful_data,line_num);            end_page_line_num = line_num;           }    }   // libc_printf("%s():enter loop\n",__FUNCTION__);	for(j=start_byte;j<end_byte;j++,data++)
	{
		#ifdef PRINTF_PAGE_PACKET
		if( cb->page_id == draw_page_id)
		{
			soc_printf(" ");
			if(line_num == draw_page_line)
			{
				soc_printf("%x",(*data));
				if(j == draw_page_col)
				{
					soc_printf(" ",(*data));
				}
			}
		}
		#endif
		tempdata=(*data)&0x7F;//cloud
		display_enable = (box_display == 1)?box_start:1;
		//if(cb->page_id==210 && line_num==0)
		//{
		//       LIBC_PRINTF("0x%x,%d" ,tempdata,j);
		//       hold_mosiac=0x%x,real_mosiac=0x%x,last_mosiac=0x%x,alpha_mosiac=0x%x,fg_color=0x%x,bg_color=0x%x\n",
		//        tempdata,j,hold_mosiac,real_mosiac,last_mosiac,alpha_mosiac,fg_color,bg_color);
		//}
		if (tempdata < 0x20)
		{
			if(hold_mosiac == 0)
				real_mosiac = 0x20;
			else
				real_mosiac = last_mosiac;
			switch(tempdata)
			{
			case 0x00://Black
			case 0x01://Red
			case 0x02://Green 
			case 0x03://Yellow 
			case 0x04://Blue
			case 0x05://Magenta
			case 0x06://Cyan
			case 0x07://White,  set fg color
				hold_mosiac = 0;
				alpha_mosiac = 1;			//cause to bug
			//	if(!(tempdata==0 && bg_color==8 && fg_color!=7))//cloud
					fg_color = tempdata;
				pre_bg_color = fg_color+8;
				if(real_alpha_mosiac == 1)//alpha
					real_mosiac = 0x20;
			break;	
            case 0x08:               ttx_flash_flag = 1;//value 1 means have start flag               ttx_flash_start_column = j;               if(ttx_flash_test_num==0)               {                    ttx_flash_task_creat();                    ttx_flash_test_num = 1;               }                             break;            case 0x09:                ttx_flash_flag = 2;//value 2 means have end flag                break;			case 0x0A://End Box
				box_start = 0;
			if((g_ttx_pconfig_par.ttx_color_number==16 && cb->Subtitle==1 && cb->SuppressHeader==1 && cb->ErasePage==0) && ((cb->MagazineSerial==0)|| 
				(cb->MagazineSerial==1 && cb->UpdateIndicator==1 && cb->InterruptedSequence==1)))//cloud, for stream 2010-1-28-12-37-205500-7-T.ts,need to erase lefted space
				TTX_ClearScreen((j+1)*TTX_CHAR_W+osd_ttx_xoffset,line_num*TTX_CHAR_H+osd_ttx_yoffset,(40-j)*TTX_CHAR_W,TTX_CHAR_H*2,TTX_B_BLACK);
				//Ryan
			if(g_ttx_pconfig_par.ttx_color_number==256 && cb->Subtitle==1 && cb->SuppressHeader==1 )
			{
				clear_extra_data =0;
				if((cb->ErasePage==0) && ((cb->MagazineSerial==0)|| (cb->MagazineSerial==1 && cb->UpdateIndicator==1 && cb->InterruptedSequence==1)))//cloud, for stream 2010-1-28-12-37-205500-7-T.ts,need to erase lefted space
					clear_extra_data =1;
				if((cb->ErasePage==1) && (cb->MagazineSerial==0) && (cb->InterruptedSequence==1))
					clear_extra_data =1;	
				if(clear_extra_data)
				{	
                    TTX_ClearScreen((j+1)*TTX_CHAR_W+osd_ttx_xoffset,line_num*TTX_CHAR_H+osd_ttx_yoffset,(40-j)*TTX_CHAR_W,TTX_CHAR_H*2,TTX_TRANSPARENT);	  
                    if(line_num == 22) 
                    {
                        ttxsubt_double_line_show = FALSE;
                    }
                }
		    }
			break;			
			case 0x0B://Start Box
				//if(prev_data == 0x0b || check_displayable_char(&tempdata, end_byte-j))
				if(check_displayable_char(data, end_byte-j))
					box_start = 1;
				if(g_ttx_pconfig_par.ttx_color_number==16 && cb->MagazineSerial==0 && cb->Subtitle==1 && cb->SuppressHeader==1 && cb->ErasePage==0)
					TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset+line_num*TTX_CHAR_H,(j+1)*TTX_CHAR_W,TTX_CHAR_H*2,TTX_B_BLACK);
				//Ryan
				if(g_ttx_pconfig_par.ttx_color_number==256&& cb->MagazineSerial==0 && cb->Subtitle==1 && cb->SuppressHeader==1 && 
					((cb->ErasePage==0) || ((cb->ErasePage==1) && (cb->InterruptedSequence==1))))
				{
            		if(j<39)
            		{
//                        if(line_num == 20) 
//                        {
//                            ttxsubt_double_line_show = TRUE;
//                        }
//                        //                        if((line_num == 22)&&(ttxsubt_double_line_show == FALSE))
//                        {
//                            TTX_ClearScreen(0,20*TTX_CHAR_H,OSD_TTX_WIDTH,TTX_CHAR_H*2,TTX_TRANSPARENT);//cloud, remove extra blank
//                            TTX_ClearScreen(0,line_num*TTX_CHAR_H,(j+1)*TTX_CHAR_W,TTX_CHAR_H*2,TTX_TRANSPARENT);
//                        }
//                        else
                           TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset+line_num*TTX_CHAR_H,(j+1)*TTX_CHAR_W,TTX_CHAR_H*2,TTX_TRANSPARENT);
            		}
            		else                      
                		TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset+line_num*TTX_CHAR_H,osd_ttx_width,TTX_CHAR_H*2,TTX_TRANSPARENT);//cloud, remove extra blank
        		}
			break;			
			case 0x0c://Normal Size
				hold_mosiac = 0;
				if(height == 1)
				{
					height=width = 0x00;
					draw_next_line = 1;
				}
				else
				{
					width = 0x00;
				}
				real_width =width;
				real_height =height;
				if(real_alpha_mosiac == 1)//alpha
					real_mosiac = 0x20;
			break;			
			case 0x0d://Double Height
				hold_mosiac = 0;
				if(double_line == 0)
				{
					cb->complement_line |= (1<<(line_num+1));						
					double_line = 1;
					draw_next_line = 1;
					alpha = alpha1;//cloud,avoid change alpha twice
					goto LineStart;
				}
				height = 0x01;
				if(real_alpha_mosiac == 1)//alpha
				real_mosiac = 0x20;
			break;			
			case 0x0e://Double Width
				hold_mosiac = 0;
				width = 0;//0x01;  we don't support Double Width now
				if(real_alpha_mosiac == 1)//alpha
				real_mosiac = 0x20;
			break;			
			case 0x0f://Double Size
				hold_mosiac = 0;
				if(double_line == 0)
				{
					cb->complement_line |= (1<<(line_num+1));						
					double_line = 1;
					draw_next_line = 1;
					alpha = alpha1;//cloud,avoid change alpha twice
					goto LineStart;
				}
				height=0x1;//width = 0x01;we don't support Double Width now
				width =0;
				if(real_alpha_mosiac == 1)//alpha
				real_mosiac = 0x20;
			break;			
			case 0x10://Mosaics Black 
			case 0x11://Mosaics Red
			case 0x12://Mosaics Green 
			case 0x13://Mosaics Yellow
			case 0x14://Mosaics Blue
			case 0x15://Mosaics Magenta
			case 0x16://Mosaics Cyan
			case 0x17://Mosaics White,  Mosaic Colour Codes
				alpha_mosiac = 0;
				fg_color = *data - 0x10;
				pre_bg_color = fg_color+8;
			break;			
			case 0x18://Conceal
				conceal = 1;
			break;			
			case 0x19://Contiguous Mosaic Graphics
				continous = 0x01;
			break;			
			case 0x1a://Separated Mosaic Graphics
				continous = 0x00;
			break;
			case 0x1b://ESC 
				alpha = (alpha==alpha1)?alpha2:alpha1;
			break;
			case 0x1c://Black Background 
				bg_color = TTX_B_BLACK;
				real_bg_color =bg_color;
			break;
			case 0x1d://New Background
				bg_color = pre_bg_color;
				real_bg_color =bg_color;
			break;
			case 0x1e://Hold Mosaics
				hold_mosiac = 1;
				real_mosiac = last_mosiac;
			break;
			case 0x1f://Release Mosaics
				hold_mosiac = 0;
			break;
			default :
			break;
			}
			if(double_width_hold == 0)
			{
				if(real_alpha_mosiac == 0)
				{
					if(display_enable ==1)
					{
						g_ttx_pconfig_par.ttx_drawchar(j*TTX_CHAR_W, line_num*TTX_CHAR_H, mosiac, real_fg_color, real_bg_color, real_width, real_height, real_mosiac, 0);
						if(g_ttx_pconfig_par.erase_unknown_packet==TRUE)
						{
							g_packet_exist[mag][line_num] = 1;
							if(real_height == 1)
							{
								g_packet_exist[mag][line_num+1] = 1;
							}
						}               
					}
				}
				else
				{
					if(display_enable ==1)
					{
						g_ttx_pconfig_par.ttx_drawchar(j*TTX_CHAR_W, line_num*TTX_CHAR_H, mosiac, real_fg_color, real_bg_color, real_width, real_height, 0x20, 0);  
						if(g_ttx_pconfig_par.erase_unknown_packet==TRUE)
						{
							g_packet_exist[mag][line_num] = 1;
							if(real_height == 1)
							{
								g_packet_exist[mag][line_num+1] = 1;
							}
						}
					}
				}
				if(draw_next_line == 1)
				{
					if(display_enable ==1)
					{
						g_ttx_pconfig_par.ttx_drawchar(j*TTX_CHAR_W, (line_num+1)*TTX_CHAR_H, mosiac, real_fg_color, real_bg_color, real_width, real_height, 0x20,0);
						if(g_ttx_pconfig_par.erase_unknown_packet==TRUE)
						{
							g_packet_exist[mag][line_num+1] = 1;
							if(real_height == 1)
								g_packet_exist[mag][line_num+2] = 1;              
						}
					}
				}
			}
			else
				double_width_hold = 0;
		}
		else if (tempdata >= 0x20 && tempdata < 0x80)//cloud
		{   
			if(alpha_mosiac == 1)
			{
				char_set = alpha;
			}
			else
			{
				if((tempdata==0x40)||(tempdata>=0x5b&&tempdata<=0x5f))
					char_set = alpha;
				else
					char_set = mosiac;
				if(hold_mosiac == 1)//cloud
				{
					if(tempdata<0x41 || tempdata>0x5a)
						last_mosiac = tempdata;
				}
				else
					last_mosiac = tempdata;
			}
			if(display_enable ==1)
			{
				if(g_ttx_pconfig_par.parse_packet26_enable==TRUE)
				{
					if((bUpd_subpage_p26 == FALSE) || (g_ttx_pconfig_par.ttx_sub_page == FALSE))
						p26_char_set = get_packet26_nation_map(cb->page_id, line_num, j);
					else
						p26_char_set = get_subpage_nation_map(cb->sub_page_id, line_num, j); 
				}
				mosaic_mode = continous;
				g_ttx_pconfig_par.ttx_drawchar(j*TTX_CHAR_W, line_num*TTX_CHAR_H, char_set, real_fg_color, real_bg_color, real_width, real_height, *data, p26_char_set);
				if(g_ttx_pconfig_par.erase_unknown_packet==TRUE)
				{
					g_packet_exist[mag][line_num] = 1;
					if(real_height == 1)
					{
						g_packet_exist[mag][line_num+1] = 1;
					}
				}             
			}
			if(draw_next_line == 1)
			{
				if(display_enable ==1)
				{
					g_ttx_pconfig_par.ttx_drawchar(j*TTX_CHAR_W, (line_num+1)*TTX_CHAR_H, mosiac, real_fg_color, real_bg_color, real_width, real_height, 0x20,0); 
					if(g_ttx_pconfig_par.erase_unknown_packet==TRUE)
					{
						g_packet_exist[mag][line_num+1] = 1;
						if(real_height == 1)
							g_packet_exist[mag][line_num+2] = 1;
					}              
				}
			}

			if(real_width ==1)
			    double_width_hold = 1;
            if((TRUE == ttx_show_on)&&(1==ttx_flash_flag)&&(NULL == p_node)&&(j>=ttx_flash_start_column)&&(last_cur_page!=cur_page||last_cur_subpage!=cur_subpage))            {                p_node=(ttx_flash_node *)malloc(sizeof(ttx_flash_node));                if(NULL == p_node)                {                }                else                {                    u_left =j*TTX_CHAR_W+osd_ttx_xoffset;                    u_top = line_num*TTX_CHAR_H+osd_ttx_yoffset;                    if(real_height== 1)                         u_height = TTX_CHAR_H*2;                    else                        u_height = TTX_CHAR_H;                   osal_mutex_lock(ttx_flash_mutex, OSAL_WAIT_FOREVER_TIME);                    p_node->left =u_left;                    p_node->top = u_top;                    p_node->width = TTX_CHAR_W;                    p_node->height = u_height;                    p_node->fg_color =real_fg_color;                    p_node->bg_color = real_bg_color;                    p_node->next = ttx_flash_list;                    ttx_flash_list = p_node;                    p_node = NULL;                    osal_mutex_unlock(ttx_flash_mutex);                }            }            		}
      		prev_data = tempdata;
		real_alpha_mosiac = alpha_mosiac;
		real_fg_color = fg_color;
		real_bg_color =bg_color;
		real_width =width;
		real_height =height;
		if(height==1)	
			draw_next_line = 0;
	} 
}
void parse_line_ext(struct PBF_CB * cb)
{
	UINT8 j;
	UINT8 *data ;
	UINT8 char_set;
	UINT8 alpha_mosiac ;
	UINT8 fg_color ;
	UINT8 pre_bg_color;
	UINT8 bg_color ;
	UINT8 width ;
	UINT8 height ;
	UINT8 conceal ;
	UINT8 continous ;
	UINT8 hold_mosiac;

	UINT8 real_alpha_mosiac ;
	UINT8 real_mosiac;
	UINT8 last_mosiac;
	UINT8 real_fg_color;
	UINT8 real_bg_color;
	UINT8 real_width;
	UINT8 real_height;
	UINT8 alpha=0x01;
	UINT8 mosiac=0xb0;
	if(cb->InhibitDisplay == 1)
		return;
	real_alpha_mosiac = alpha_mosiac = 1;
	real_fg_color = fg_color = TTX_F_WHITE;
	pre_bg_color = TTX_B_WHITE;
	real_bg_color = bg_color = TTX_B_BLACK;
	real_width = width = 0;
	real_height = height = 0;
	conceal = 0;
	continous = 1;
	hold_mosiac = 0;
	real_mosiac =0x20;
	last_mosiac =0x20;
    if(cb->Subtitle||cb->Newsflash)
	{
		return;
	}
    for(j=0;j<80;j++)
    {
        if(g_SubPages[j]->valid==1&&g_SubPages[j]->pack24_exist==1)
            return;
    }
	//else
	{
		data = link_line_data;
		if(queue_tag ==4)
		{
			MEMSET(link_line_data,0x20,40);
			link_line_data[0] = 0x01;
			link_line_data[1] = 0x1d;
			link_line_data[2] = 0x07;
			link_line_data[4] = (UINT8)(page_queue[0]/100) + 0x30;
			link_line_data[5] = (UINT8)((page_queue[0]%100)/10) + 0x30;
			link_line_data[6] = (UINT8)((page_queue[0]%100)%10) + 0x30;
			link_line_data[9] = 0x02;
			link_line_data[10] = 0x1d;
			link_line_data[11] = 0x04;
			link_line_data[13]= (UINT8)(page_queue[1]/100) + 0x30;
			link_line_data[14]= (UINT8)((page_queue[1]%100)/10) + 0x30;
			link_line_data[15] = (UINT8)((page_queue[1]%100)%10) + 0x30;
			link_line_data[19] = 0x03;
			link_line_data[20] = 0x1d;
			link_line_data[21] = 0x04;
			link_line_data[23] = (UINT8)(page_queue[2]/100) + 0x30;
			link_line_data[24] = (UINT8)((page_queue[2]%100)/10) + 0x30;
			link_line_data[25] = (UINT8)((page_queue[2]%100)%10) + 0x30;
			link_line_data[29] = 0x06;
			link_line_data[30] = 0x1d;
			link_line_data[31] = 0x04;
            if((page_queue[3]==0xffff) && (new_history_mode==TRUE))
            {
                link_line_data[32] = (UINT8)'v';
                link_line_data[33] = (UINT8)'o';
			    link_line_data[34] = (UINT8)'i';
			    link_line_data[35] = (UINT8)'d';
            }
            else
            {
			    link_line_data[33] = (UINT8)(page_queue[3]/100) + 0x30;
			    link_line_data[34] = (UINT8)((page_queue[3]%100)/10) + 0x30;
			    link_line_data[35] = (UINT8)((page_queue[3]%100)%10) + 0x30;
            }
		}
		else if(queue_tag ==3)
		{
			MEMSET(link_line_data,0x20,40);
			link_line_data[0] = 0x01;
			link_line_data[1] = 0x1d;
			link_line_data[2] = 0x07;
			link_line_data[6] = (UINT8)(page_queue[0]/100) + 0x30;
			link_line_data[7] = (UINT8)((page_queue[0]%100)/10) + 0x30;
			link_line_data[8] = (UINT8)((page_queue[0]%100)%10) + 0x30;
			link_line_data[14] = 0x02;
			link_line_data[15] = 0x1d;
			link_line_data[16] = 0x04;
			link_line_data[20]= (UINT8)(page_queue[1]/100) + 0x30;
			link_line_data[21]= (UINT8)((page_queue[1]%100)/10) + 0x30;
			link_line_data[22] = (UINT8)((page_queue[1]%100)%10) + 0x30;
			link_line_data[28] = 0x03;
			link_line_data[29] = 0x1d;
			link_line_data[30] = 0x04;
			link_line_data[34] = (UINT8)(page_queue[2]/100) + 0x30;
			link_line_data[35] = (UINT8)((page_queue[2]%100)/10) + 0x30;
			link_line_data[36] = (UINT8)((page_queue[2]%100)%10) + 0x30;
		}
		else if(queue_tag ==2)
		{
			MEMSET(link_line_data,0x20,40);
			link_line_data[0] = 0x01;
			link_line_data[1] = 0x1d;
			link_line_data[2] = 0x07;
			link_line_data[9] = (UINT8)(page_queue[0]/100) + 0x30;
			link_line_data[10] = (UINT8)((page_queue[0]%100)/10) + 0x30;
			link_line_data[11] = (UINT8)((page_queue[0]%100)%10) + 0x30;
			link_line_data[21] = 0x02;
			link_line_data[22] = 0x1d;
			link_line_data[23] = 0x04;
			link_line_data[29]= (UINT8)(page_queue[1]/100) + 0x30;
			link_line_data[30]= (UINT8)((page_queue[1]%100)/10) + 0x30;
			link_line_data[31] = (UINT8)((page_queue[1]%100)%10) + 0x30;
		}
		else if(queue_tag ==1)
		{
			MEMSET(link_line_data,0x20,40);
			link_line_data[0] = 0x01;
			link_line_data[1] = 0x1d;
			link_line_data[2] = 0x07;
			link_line_data[19] = (UINT8)(page_queue[0]/100) + 0x30;
			link_line_data[20] = (UINT8)((page_queue[0]%100)/10) + 0x30;
			link_line_data[21] = (UINT8)((page_queue[0]%100)%10) + 0x30;
		}
	}

	for(j=0;j<40;j++,data++)
	{
		if (*data < 0x20)
		{
			if(hold_mosiac == 0)
				real_mosiac = 0x20;
			else
				real_mosiac = last_mosiac;
			switch(*data)
			{
				case 0x00:
				case 0x01:
				case 0x02:
				case 0x03:
				case 0x04:
				case 0x05:
				case 0x06:
				case 0x07:
					alpha_mosiac = 1;
					fg_color = *data;
					pre_bg_color = fg_color+8;
					if(real_alpha_mosiac == 1)//alpha
						real_mosiac = 0x20;
					break;
				case 0x0c:
					break;
				case 0x0d:
					break;
				case 0x0e:
					break;
				case 0x0f:
					break;
				case 0x10:
				case 0x11:
				case 0x12:
				case 0x13:
				case 0x14:
				case 0x15:
				case 0x16:
				case 0x17:
					alpha_mosiac = 0;
					fg_color = *data - 0x10;
					pre_bg_color = fg_color+8;
					break;
				case 0x18:
					conceal = 1;
					break;
				case 0x19:
					continous = 0x01;
					break;
				case 0x1a:
					continous = 0x00;
					break;
				case 0x1b:
					break;
				case 0x1c:
					bg_color = TTX_B_BLACK;
					real_bg_color =bg_color;
					break;
				case 0x1d:
					bg_color = pre_bg_color;
					real_bg_color =bg_color;
					break;
				case 0x1e:
					hold_mosiac = 1;
					real_mosiac = last_mosiac;
					break;
				case 0x1f:
					hold_mosiac = 0;
					break;
				default :
					break;
			}
			if(real_alpha_mosiac == 0)				g_ttx_pconfig_par.ttx_drawchar(j*TTX_CHAR_W, 24*TTX_CHAR_H, mosiac, real_fg_color, real_bg_color, real_width, real_height, real_mosiac,0);
			else
				g_ttx_pconfig_par.ttx_drawchar(j*TTX_CHAR_W, 24*TTX_CHAR_H, mosiac, real_fg_color, real_bg_color, real_width, real_height, 0x20,0);
		}
		else if (*data >= 0x20 && *data < 0x80)
		{
			if(alpha_mosiac == 1)
			{
				char_set = alpha;
			}
			else
			{
				char_set = mosiac;
				last_mosiac = *data;
			}
			g_ttx_pconfig_par.ttx_drawchar(j*TTX_CHAR_W, 24*TTX_CHAR_H, char_set, real_fg_color, real_bg_color, real_width, real_height, *data,0);
		}
		real_alpha_mosiac = alpha_mosiac;
		real_fg_color = fg_color;
		real_bg_color =bg_color;
		real_width =width;
		real_height =height;
	}
}
void show_ttx_info()
{
    UINT8 i,j;
	UINT8 *data ;
	UINT8 char_set;
	UINT8 alpha_mosiac ;
	UINT8 fg_color ;
	UINT8 pre_bg_color;
	UINT8 bg_color ;
	UINT8 width ;
	UINT8 height ;
	UINT8 conceal ;
	UINT8 continous ;
	UINT8 hold_mosiac;

	UINT8 real_alpha_mosiac ;
	UINT8 real_mosiac;
	UINT8 last_mosiac;
	UINT8 real_fg_color;
	UINT8 real_bg_color;
	UINT8 real_width;
	UINT8 real_height;
    UINT8 ttx_info[40];
	UINT8 alpha=0x01;
	UINT8 mosiac=0xb0;

	real_alpha_mosiac = alpha_mosiac = 1;
	real_fg_color = fg_color = TTX_F_WHITE;
	pre_bg_color = TTX_B_WHITE;
	real_bg_color = bg_color = TTX_TRANSPARENT;//TTX_B_BLACK;
	real_width = width = 0;
	real_height = height = 0;
	conceal = 0;
	continous = 1;
	hold_mosiac = 0;
	real_mosiac =0x20;
	last_mosiac =0x20;
    for(i=0;i<15;i++)
        ttx_info[i]=0x20;
    for(i=24;i<40;i++)
         ttx_info[i]=0x20;
    ttx_info[15]=TTX_F_RED;
    ttx_info[16]='T';
    ttx_info[17]='e';
    ttx_info[18]='l';
    ttx_info[19]='e';
    ttx_info[20]='t';
    ttx_info[21]='e';
    ttx_info[22]='x';
    ttx_info[23]='t';
    data=ttx_info;
    for(j=0;j<40;j++,data++)
	{
		if (*data < 0x20)
		{
			if(hold_mosiac == 0)
				real_mosiac = 0x20;
			else
				real_mosiac = last_mosiac;
			switch(*data)
			{
				case 0x00:
				case 0x01:
				case 0x02:
				case 0x03:
				case 0x04:
				case 0x05:
				case 0x06:
				case 0x07:
					alpha_mosiac = 1;
					fg_color = *data;
					pre_bg_color = fg_color+8;
					if(real_alpha_mosiac == 1)//alpha
						real_mosiac = 0x20;
					break;
				case 0x0c:
					break;
				case 0x0d:
					break;
				case 0x0e:
					break;
				case 0x0f:
					break;
				case 0x10:
				case 0x11:
				case 0x12:
				case 0x13:
				case 0x14:
				case 0x15:
				case 0x16:
				case 0x17:
					alpha_mosiac = 0;
					fg_color = *data - 0x10;
					pre_bg_color = fg_color+8;
					break;
				case 0x18:
					conceal = 1;
					break;
				case 0x19:
					continous = 0x01;
					break;
				case 0x1a:
					continous = 0x00;
					break;
				case 0x1b:
					break;
				case 0x1c:
					bg_color = TTX_B_BLACK;
					real_bg_color =bg_color;
					break;
				case 0x1d:
					bg_color = pre_bg_color;
					real_bg_color =bg_color;
					break;
				case 0x1e:
					hold_mosiac = 1;
					real_mosiac = last_mosiac;
					break;
				case 0x1f:
					hold_mosiac = 0;
					break;
				default :
					break;
			}
			if(real_alpha_mosiac == 0)
				g_ttx_pconfig_par.ttx_drawchar(j*TTX_CHAR_W, 26*TTX_CHAR_H, mosiac, real_fg_color, real_bg_color, real_width, real_height, real_mosiac,0);
			else
				g_ttx_pconfig_par.ttx_drawchar(j*TTX_CHAR_W, 26*TTX_CHAR_H, mosiac, real_fg_color, real_bg_color, real_width, real_height, 0x20,0);
		}
		else if (*data >= 0x20 && *data < 0x80)
		{			if(alpha_mosiac == 1)
			{
				char_set = alpha;
			}
			else
			{
				char_set = mosiac;
				last_mosiac = *data;
			}
			g_ttx_pconfig_par.ttx_drawchar(j*TTX_CHAR_W, 26*TTX_CHAR_H, char_set, real_fg_color, real_bg_color, real_width, real_height, *data,0);
		}
		real_alpha_mosiac = alpha_mosiac;
		real_fg_color = fg_color;
		real_bg_color =bg_color;
		real_width =width;
		real_height =height;
	}
}
void set_packet24_new(struct vbi_device *ttx_dev, UINT16 last_page_num)
{
    INT32 ret=0;
    struct PBF_CB * temp_cb=NULL;  
    ret = ttx_request_page_up(ttx_dev,cur_page, &temp_cb);
    if (ret == RET_SUCCESS)
        page_queue[0] = temp_cb->page_id;
    else
        page_queue[0] = cur_page;
    ret = ttx_request_page_up(ttx_dev,page_queue[0], &temp_cb);
    if (ret == RET_SUCCESS)
        page_queue[1] = temp_cb->page_id;
    else
        page_queue[1] = page_queue[0];
    ret = ttx_request_page_up(ttx_dev,page_queue[1], &temp_cb);
    if (ret == RET_SUCCESS)
        page_queue[2] = temp_cb->page_id;
    else
        page_queue[2] = page_queue[1];
    queue_tag = 4;
	page_queue[3] = last_page_num;
}
OSAL_ID	ttx_subt_alarm_id = OSAL_INVALID_ID;    // used for ttx subt clear
void ttx_subt_page_timeout_handler(void)
{
    if(g_ttx_pconfig_par.ttx_color_number==256)
        TTX_SetScreenColor(TTX_TRANSPARENT);
    if(ttx_subt_alarm_id != OSAL_INVALID_ID)
    {
        osal_timer_delete(ttx_subt_alarm_id);
        ttx_subt_alarm_id = OSAL_INVALID_ID;
    }
}
void ttx_subt_timer_start(void)
{
  OSAL_T_CTIM 	ttx_subt_timer;
  if(ttx_subt_alarm_id != OSAL_INVALID_ID)
  { 
    osal_timer_delete(ttx_subt_alarm_id);
    ttx_subt_alarm_id = OSAL_INVALID_ID;
  }
  ttx_subt_timer.type = TIMER_ALARM;
  ttx_subt_timer.time = 5000;//2000;
  ttx_subt_timer.callback = ttx_subt_page_timeout_handler;
  ttx_subt_alarm_id = osal_timer_create(&ttx_subt_timer); 
}
INT32 ttx_eng_open(struct vbi_device *ttx_dev, UINT8 subtitle,UINT16 page_num)
{//to create and start task or wake up a task
	INT32 ret;
	UINT8 i;
	UINT16 left;
	UINT16 top;
	UINT8 ch;

	//LIBC_PRINTF("TTXEng OPEN : subtitle = %d,page_num = %d\n",subtitle,page_num);
	ENTER_TTX_ENG();
	screen_transparent_flag=0;
	screen_transparent_flag2=0;
    if(g_ttx_pconfig_par.user_fast_text==TRUE)
    {
    	page_queue[0] = 0xffff;
    	page_queue[1] = 0xffff;
    	page_queue[2] = 0xffff;
    	page_queue[3] = 0xffff;
    	queue_tag = 0;
        MEMSET(link_line_data,0x20,40);
    }
	req_page = page_num;
	WaitPage = req_page;
	pCurRdCB = NULL;
	cur_page = 0xffff;
    if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
    {
        bUpdPage = FALSE;//
        cur_subpage = 0xffff;
        WaitSubPage = 0xffff;//cloud
        init_SubPageCB();//cloud
    }
	if(subtitle != 1)
	{
        if(g_ttx_pconfig_par.ttx_color_number==16)
        {
    		TTX_SetBackAlpha(transparent_value[transparent_level]);
    		TTX_SetScreenColor(TTX_B_BLACK);
        }
        if(g_ttx_pconfig_par.ttx_color_number==256)
    		TTX_SetScreenColor(TTX_B_BLACK);
		top = 0;
		//left = 0;
		//ch = 'P';
		//ENG_PRINTF("=> %c \n", ch);
		//TTX_DrawChar(left,top,0x01,TTX_F_WHITE,TTX_B_BLACK,0,0,ch);
		left = TTX_CHAR_W;
		//ch = '1';
		ch = (UINT8)(req_page/100) + 0x30;
		//ENG_PRINTF("=> %c \n", ch);
		g_ttx_pconfig_par.ttx_drawchar(left,top,0x01,TTX_F_WHITE,TTX_B_BLACK,0,0,ch,0);
		left = TTX_CHAR_W*2;
		//ch = '0';
		ch = (UINT8)((req_page%100)/10) + 0x30;
		//ENG_PRINTF("=> %c \n", ch);
		g_ttx_pconfig_par.ttx_drawchar(left,top,0x01,TTX_F_WHITE,TTX_B_BLACK,0,0,ch,0);
		left = TTX_CHAR_W*3;
		//ch = '0';
		ch = (UINT8)((req_page%100)%10) + 0x30;
		//ENG_PRINTF("=> %c \n", ch);
		g_ttx_pconfig_par.ttx_drawchar(left,top,0x01,TTX_F_WHITE,TTX_B_BLACK,0,0,ch,0);
		ret = ttx_request_page(ttx_dev,req_page , &pCurRdCB );
		if (ret == RET_SUCCESS)
		{
			WaitPage =0xffff;
			cur_page = pCurRdCB->page_id;          
            if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
                cur_subpage = pCurRdCB->sub_page_id;			parse_line(pCurRdCB,0,0,1);
			for(i=1;i<25;i++)
				parse_line(pCurRdCB,i,0,0);
            if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
            {
                //for(i=0;i<25;i++)
                set_SubPageCB(pCurRdCB->sub_page_id, pCurRdCB, 0, 24, FALSE);
                show_subpage_status();
            }      
		}
	}
	else
	{
        if(g_ttx_pconfig_par.ttx_color_number==16)
        {
    		TTX_SetBackAlpha(transparent_value[TTX_TRANSPARENT_LEVEL-1]);
    		TTX_SetScreenColor(TTX_B_BLACK);
        }
        if(g_ttx_pconfig_par.ttx_color_number==256)
    		TTX_SetScreenColor(TTX_TRANSPARENT);
		ret = ttx_request_page(ttx_dev,req_page , &pCurRdCB );
		if (ret == RET_SUCCESS && pCurRdCB->page_id == req_page)        
		{
			WaitPage =0xffff;
			cur_page = pCurRdCB->page_id;  
            if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
                cur_subpage = pCurRdCB->sub_page_id;
			for(i=1;i<25;i++)
				parse_line(pCurRdCB,i,0,0);
		}
	}
	ttx_eng_state = subtitle;

    if((g_ttx_pconfig_par.user_fast_text==TRUE) && (new_history_mode==TRUE))
    {
        set_packet24_new(ttx_dev, 0xffff);
        if(pCurRdCB && pCurRdCB->pack24_exist == 0)
    		parse_line_ext(pCurRdCB);
    }
    if(get_ttxmenu_status()== TRUE && get_ttxinfo_status() == TRUE)
    {
        show_ttx_info();
    }
    //libc_printf("TTXEng_Open finish\n");
    LEAVE_TTX_ENG();
	return SUCCESS;
}
void  ttx_eng_close(struct vbi_device *ttx_dev)
{
    //libc_printf("--TTXEng_Close--\n");
    ENTER_TTX_ENG();
	ttx_eng_state = TTXENG_OFF;
    ttx_delete_whole();	   LEAVE_TTX_ENG();
}
 static UINT16 same_cur_subpage = 0xffff;void ttx_eng_update_page(struct vbi_device *ttx_dev, UINT16 page_id, UINT8 line_id)
{
	INT32 ret;
	UINT8 i;
	struct PBF_CB * pCB;
    UINT8 *data = NULL;    UINT16 mag;    	//ttx_dev = (struct vbi_device *)dev_get_by_name("VBI_M3327_0");
	if(ttx_eng_state ==TTXENG_OFF)
	{
		return;
	}
	//osal_task_dispatch_off();
    if(page_id/100==8)		        mag=0;	    else		        mag=page_id/100;        if ((page_id == cur_page && WaitPage == 0xffff) && (pCurRdCB!= NULL))
	{//diplaying & not waiting
        if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
        {                        
            if(line_id == 0 )
    		{
                parse_line(pCurRdCB,0,1,0);
    		    set_SubPageCB(pCurRdCB->sub_page_id, pCurRdCB, 0, 0, FALSE);
                end_line_of_the_page = 0;                for(i=1;i<25;i++)                                {                    if(1 == g_packet_exist[mag][i])                        end_line_of_the_page = i;                }                                #if 0                                                if(1 == pCurRdCB->Subtitle)                {                                       UINT32 temp_tick;                                       temp_tick = osal_get_tick();                   if(temp_tick - last_temp_tick>2000)                       TTX_SetScreenColor(TTX_TRANSPARENT);                                       last_temp_tick = temp_tick;                                }                                #endif                         
             }            //LIBC_PRINTF("cur_page=%d,cur_subpage=%d,bUpdPage=%d,WaitSubPage=%d,pCurRdCB->sub_page_id=%d\n",
            //             cur_page,cur_subpage,bUpdPage,WaitSubPage,pCurRdCB->sub_page_id);            for( i=0;i<=24;i++)            {
            	data = pCurRdCB->buf_start + (40*i);            	if(check_displayable_char(data,40))            		break;            }            if((i>24)&&(1!= pCurRdCB->Subtitle))            {            	            	return;            }            if(line_id != 0 && get_bSaveSubpage())
                set_SubPageCB(pCurRdCB->sub_page_id, pCurRdCB, line_id, line_id, FALSE);         
    		if((bUpdPage==FALSE && (WaitSubPage == 0xffff)) || WaitSubPage == pCurRdCB->sub_page_id || cur_subpage == pCurRdCB->sub_page_id) //cloud
    		{
                cur_subpage = pCurRdCB->sub_page_id;
                              #if 1               // the same curpage needn't delete the ttx_flash_list link table;               // the ttx_flash_list will be delete when the subpage changed               if(same_cur_subpage == 0xffff)//pCurRdCB->sub_page_id)               {                                      same_cur_subpage = pCurRdCB->sub_page_id;               }               else               {                   if(same_cur_subpage != pCurRdCB->sub_page_id)                   {                       ttx_delete_whole();                       same_cur_subpage = pCurRdCB->sub_page_id;                   }               }               #endif                                  		    if(line_id >0 && line_id<25 )
    		    {                    if(1 == pCurRdCB->Subtitle&&cur_page==pCurRdCB->page_id)                    {                        UINT32 temp_tick = 0;                        data = pCurRdCB->buf_start + (40*line_id);                        b_useful_data= check_displayable_char(data,40);                        if(TRUE == b_useful_data)                        {                            ttx_subt_timer_start();                            temp_tick = osal_get_tick();                            if(temp_tick - last_temp_tick>1500)                            {                	  		  	                                 //libc_printf("clear screen3\n");                                TTX_SetScreenColor(TTX_TRANSPARENT);                             }                            		    	  		                              last_temp_tick = temp_tick;                             b_useful_data = FALSE;                            }      		    	 }  			        		    	  parse_line(pCurRdCB,line_id,0,0);
    		    }    		    		}
            //the stream will send a page with no useful data after sending a page with useful data.            //the screen must be cleaned when receiving the page with no useful data.                        #if 0            if(1 == pCurRdCB->Subtitle && /*24 == line_id*/end_line_of_the_page!= 0&&line_id == end_line_of_the_page)                        {                                if(TRUE == b_useful_data)                                {                                            TTX_SetScreenColor(TTX_TRANSPARENT);                         b_useful_data = FALSE;                        end_page_line_num = 24;                                }                                else                                {                                        //b_useful_data = FALSE;                                        end_page_line_num = 24;                                }                        }                #endif            if(line_id>=0 && line_id<25)
            {
                if(line_id<last_line_id)
                    show_subpage_status();
                last_line_id = line_id;
            }            if(line_id ==end_line_of_the_page)            {                last_cur_page = cur_page;            }
        }
        else
        {
            if(line_id == 0)
			    parse_line(pCurRdCB,0,1,0);
		    else
			    parse_line(pCurRdCB,line_id,0,0);
        }
	}
	else if (page_id == WaitPage)
	{//Waiting meet
		ret = ttx_request_page(ttx_dev,WaitPage , &pCurRdCB );  
		if (ret == RET_SUCCESS)            
		{
			WaitPage =0xffff;
			if(pCurRdCB == NULL)			{				return;			}			cur_page = pCurRdCB->page_id;
            parse_line(pCurRdCB,0,1,0);
            if((bUpdPage==FALSE && g_ttx_pconfig_par.ttx_sub_page==TRUE) || (g_ttx_pconfig_par.ttx_sub_page==FALSE))//
            {
			    for(i=1;i<25;i++)
				    parse_line(pCurRdCB,i,0,0);
                if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
                    show_subpage_status();//cloud
                if(pCurRdCB && pCurRdCB->pack24_exist == 0 && (g_ttx_pconfig_par.user_fast_text==TRUE))
		           parse_line_ext(pCurRdCB);
            }
		}
	}
	else if(WaitPage != 0xffff)
	{//waiting not meet
		if(line_id == 0)
		{
			ret = ttx_request_page(ttx_dev,page_id , &pCB );
			if(pCB == NULL)				            {				                return;				            }
			
            if (ret == RET_SUCCESS)            {				if(ttx_eng_state == TTXENG_TEXT && pCB->InterruptedSequence != 1)
				{
                    if(pCurRdCB == NULL || (pCurRdCB!=NULL && pCurRdCB->Newsflash!=1))
                    {
                        for(i=8;i<32;i++)
                        {
                            if(*(pCB->buf_start+i)!=0x20)
                                break;
                        }
                        if(i!=32)//filter blank packet 0
				        {			       
                             parse_line(pCB,0,1,0);				        }				     }
				}
			}
		}
	}
	return;
}
#ifdef SEE_CPU
extern struct vbi_device * g_vbi_device;
void ttx_eng_update_page_cb(UINT16 Param1,UINT8 Param2)
{
    ENTER_TTX_ENG();
    ttx_eng_update_page(g_vbi_device, Param1, Param2);
    LEAVE_TTX_ENG();
}
#endif
void  ttx_eng_show_onoff(struct vbi_device *ttx_dev, BOOL bOn)
{
    ENTER_TTX_ENG();
	if(bOn == TRUE)
	{
		MEMSET(last_draw_data, 0xFF, 24*40);
		ttx_osd_enter();
	}
	else
	{
		ttx_osd_leave();
	}
    LEAVE_TTX_ENG();
}
void ttx_eng_send_key(struct vbi_device *ttx_dev, TTX_KEYTYPE key)
{
	INT32 ret;
	UINT8 i,j;
	UINT16 left,top;
	UINT8 ch,huds,tens,ones;
	static UINT8 keystate =0;
	UINT16 last_page = 0;
	UINT16 swap_page;
	UINT8 queue_inc;
    UINT8 subpage;
    ENTER_TTX_ENG();
	//ttx_dev = (struct vbi_device *)dev_get_by_name("VBI_M3327_0");
	if(ttx_eng_state ==TTXENG_OFF)
	{
        LEAVE_TTX_ENG();
		return;
	}
	//osal_task_dispatch_off();
    if(g_ttx_pconfig_par.user_fast_text==TRUE)
	    last_page = cur_page;
/*.......................alpha...........................*/
	if (key== TTX_KEY_ALPHA )
	{
		if(transparent_level >= TTX_TRANSPARENT_LEVEL-1)
			transparent_level = 0;
		else
			transparent_level ++;
		TTX_SetBackAlpha(transparent_value[transparent_level]);
		goto EXIT_POINT;
	}
/*.......................num ............................*/
	else if (key==TTX_KEY_NUM0
		||key==TTX_KEY_NUM1
		||key==TTX_KEY_NUM2
		||key==TTX_KEY_NUM3
		||key==TTX_KEY_NUM4
		||key==TTX_KEY_NUM5
		||key==TTX_KEY_NUM6
		||key==TTX_KEY_NUM7
		||key==TTX_KEY_NUM8
		||key==TTX_KEY_NUM9)
	{
		ch = key2char(key);
		if(keystate==0 && ch >0x30 && ch<0x39)
		{
			//TTX_SetRegionColor(14,0,42,20,TTX_WHITE);
			left = TTX_CHAR_W;
			top = 0;
			req_page = (ch-0x30)*100;
			g_ttx_pconfig_par.ttx_drawchar(left,top,0x01,TTX_F_WHITE,TTX_B_BLACK,0,0,ch,0);
			left = TTX_CHAR_W*2;
			ch = '-';			g_ttx_pconfig_par.ttx_drawchar(left,top,0x01,TTX_F_WHITE,TTX_B_BLACK,0,0,ch,0);
			left = TTX_CHAR_W*3;
			ch = '-';
			g_ttx_pconfig_par.ttx_drawchar(left,top,0x01,TTX_F_WHITE,TTX_B_BLACK,0,0,ch,0);

			keystate= 1;
			goto EXIT_POINT;
		}
		else if(keystate==1)
		{
			//TTX_SetRegionColor(28,0,28,20,TTX_WHITE);
			left = TTX_CHAR_W*2;
			top = 0;
			req_page += ((ch-0x30)*10);
			g_ttx_pconfig_par.ttx_drawchar(left,top,0x01,TTX_F_WHITE,TTX_B_BLACK,0,0,ch,0);
			left = TTX_CHAR_W*3;
			ch = '-';
			g_ttx_pconfig_par.ttx_drawchar(left,top,0x01,TTX_F_WHITE,TTX_B_BLACK,0,0,ch,0);
			keystate= 2;
			goto EXIT_POINT;
		}
		else if(keystate==2)
		{
			//TTX_SetRegionColor(42,0,14,20,TTX_WHITE);
			left = TTX_CHAR_W*3;
			top = 0;
			req_page += (ch-0x30);
			g_ttx_pconfig_par.ttx_drawchar(left,top,0x01,TTX_F_WHITE,TTX_B_BLACK,0,0,ch,0);
			keystate= 0;
		}
		else
		{
			goto EXIT_POINT;
		}
		//LIBTTX_PRINTF("2. ttx_request_page %d \n",req_page);
		if(req_page!=0xffff)
		{
            if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
                clear_SubPageCB();
			ret = ttx_request_page(ttx_dev,req_page , &pCurRdCB );            
			if (ret == RET_SUCCESS)
			{
               ttx_delete_whole();               same_cur_subpage = 0xffff;				WaitPage =0xffff;
				cur_page = pCurRdCB->page_id;
                if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
                {
                    cur_subpage = pCurRdCB->sub_page_id;
                    bUpdPage = FALSE;//
                }				if((pCurRdCB->Subtitle||pCurRdCB->Newsflash) && (seperate_ttxsubtitle_mode == 0 || (get_ttxmenu_status()== FALSE)))
				{
					TTX_SetScreenColor(TTX_TRANSPARENT);
					MEMSET(last_draw_data, 0xFF, 24*40);
				}
				else
				{
					if(g_ttx_pconfig_par.ttx_color_number==256)
					{
						TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset+TTX_CHAR_H,osd_ttx_width,TTX_CHAR_H*24,TTX_B_BLACK);
						MEMSET(last_draw_data, 0xFF, 24*40);
					}
				}
				parse_line(pCurRdCB,0,0,1);
				for(i=1;i<25;i++)
				{
					parse_line(pCurRdCB,i,0,0);
				}
                if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
                {
                    //for(i=0;i<25;i++)
                    set_SubPageCB(pCurRdCB->sub_page_id, pCurRdCB, 0, 24,FALSE);
                }                  
			}
			else
			{
				//LIBTTX_PRINTF("ttx_request_page failure!\n");
				WaitPage = req_page;
			}
		}
        if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
            show_subpage_status();
		goto EXIT_POINT;
	}
/*.......................up & dowm ............................*/
	else if(key == TTX_KEY_UP)
	{
		keystate= 0;
        if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
            clear_SubPageCB();
		if(WaitPage!=0xffff)
			ret = ttx_request_page_up(ttx_dev,WaitPage , &pCurRdCB );
		else
		    ret = ttx_request_page_up(ttx_dev,cur_page , &pCurRdCB );
   
		if (ret == RET_SUCCESS)
		{
            ttx_delete_whole();            same_cur_subpage = 0xffff;			WaitPage =0xffff;
			cur_page = pCurRdCB->page_id;
            if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
            {
                cur_subpage = pCurRdCB->sub_page_id;
                bUpdPage = FALSE;//
            }
			if((pCurRdCB->Subtitle||pCurRdCB->Newsflash) && (seperate_ttxsubtitle_mode == 0 || (get_ttxmenu_status()== FALSE)))
			{
				TTX_SetScreenColor(TTX_TRANSPARENT);
				MEMSET(last_draw_data, 0xFF, 24*40);
			}
			else
			{
				if(g_ttx_pconfig_par.ttx_color_number==256)
				{
					TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset+TTX_CHAR_H,osd_ttx_width,TTX_CHAR_H*24,TTX_B_BLACK);
					MEMSET(last_draw_data, 0xFF, 24*40);
				}
			}
            pCurRdCB->complement_line = 0; //Ryan
			parse_line(pCurRdCB,0,0,1);
			for(i=1;i<25;i++)
				parse_line(pCurRdCB,i,0,0);

            if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
            {
                //for(i=0;i<25;i++)
                set_SubPageCB(pCurRdCB->sub_page_id, pCurRdCB, 0, 24, FALSE);
            }      
		}
		else
		{
			WaitPage = req_page;
		}
        if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
            show_subpage_status();
		goto EXIT_POINT;
	}
	else if(key == TTX_KEY_DOWN)
	{
		keystate= 0;
		//LIBTTX_PRINTF("KEY_DOWN %d \n", cur_page);
        if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
            clear_SubPageCB();
		if(WaitPage!=0xffff)
			ret = ttx_request_page_down(ttx_dev,WaitPage , &pCurRdCB );
		else
		ret = ttx_request_page_down(ttx_dev,cur_page , &pCurRdCB );  
        if (ret == RET_SUCCESS)
		{
//            LIBC_PRINTF("page_down Success!\n");
           ttx_delete_whole();            same_cur_subpage = 0xffff;			WaitPage =0xffff;
			cur_page = pCurRdCB->page_id;
            if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
            {
                cur_subpage = pCurRdCB->sub_page_id;
                bUpdPage = FALSE;//
            }
			if((pCurRdCB->Subtitle||pCurRdCB->Newsflash) && (seperate_ttxsubtitle_mode == 0 || (get_ttxmenu_status()== FALSE)))
			{
				TTX_SetScreenColor(TTX_TRANSPARENT);
				MEMSET(last_draw_data, 0xFF, 24*40);
			}
			else
			{
				if(g_ttx_pconfig_par.ttx_color_number==256)
				{
					TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset+TTX_CHAR_H,osd_ttx_width,TTX_CHAR_H*24,TTX_B_BLACK);
					MEMSET(last_draw_data, 0xFF, 24*40);
				}
			}            pCurRdCB->complement_line = 0; //Ryan
			parse_line(pCurRdCB,0,0,1);
			for(i=1;i<25;i++)
				parse_line(pCurRdCB,i,0,0);
            if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
            {
                //for(i=0;i<25;i++)
                set_SubPageCB(pCurRdCB->sub_page_id, pCurRdCB,0,24,FALSE);
            }       
		}
		else
		{
//			LIBC_PRINTF("page_down fail!\n");
			WaitPage = req_page;
		}
        if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
            show_subpage_status();
		goto EXIT_POINT;
	}
/*.......................left & right ............................*/
	else if(key == TTX_KEY_RIGHT && g_ttx_pconfig_par.ttx_sub_page==TRUE)
	{
        //ttx_gen_char_code();
		keystate= 0;
        //LIBC_PRINTF("TTX_KEY_RIGHT, WaitPage=%d,WaitSubPage=%d,cur_page=%d,cur_subpage=%d\n", 
        //    WaitPage,WaitSubPage,cur_page,cur_subpage);
        if(cur_subpage == 0xffff || cur_subpage == 79)
            goto EXIT_POINT;     
        subpage = cur_subpage;     
		ret = ttx_request_sub_page_up(cur_page , subpage, &pCurRdCB );
        
		if (ret == RET_SUCCESS)
		{
			//LIBC_PRINTF("subpage_up Success!\n");
			ttx_delete_whole();			bUpd_subpage_p26 = TRUE;
			WaitSubPage =0xffff;
			cur_page = pCurRdCB->page_id;
            cur_subpage = pCurRdCB->sub_page_id;
			if(g_ttx_pconfig_par.ttx_color_number==256)
			{
				TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset+TTX_CHAR_H,osd_ttx_width,TTX_CHAR_H*24,TTX_B_BLACK);
				MEMSET(last_draw_data, 0xFF, 24*40);
			}

			parse_line(pCurRdCB,0,0,1);
			for(i=1;i<25;i++)
			{
                //LIBC_PRINTF("sub_page_up,i=%d\n",i);
				parse_line(pCurRdCB,i,0,0);
			}
            WaitPage = pCurRdCB->page_id;
            bUpd_subpage_p26 = FALSE;
            show_subpage_status();
		}
		else
		{
			//LIBC_PRINTF("subpage_up Failure!\n");
			if(subpage < 79 && subpage >0)
			    WaitSubPage=subpage+1;
		}
        if(cur_subpage!=0)
            bUpdPage = TRUE;
        else
            bUpdPage = FALSE;
        //LIBC_PRINTF("TTX_KEY_RIGHT,WaitSubPage=%d\n",WaitSubPage); 
		goto EXIT_POINT;
	}
	else if(key == TTX_KEY_LEFT)
	{
		keystate= 0;
		//LIBC_PRINTF("TTX_KEY_LEFT, WaitPage=%d,WaitSubPage=%d,cur_page=%d,cur_subpage=%d\n", 
         //   WaitPage,WaitSubPage,cur_page,cur_subpage);
        if(cur_subpage == 0 || cur_subpage== 0xffff || (status_line_data[2] == TTX_F_RED && status_line_data[3] == 0x41))
            goto EXIT_POINT;
       // LIBC_PRINTF("begin to subpage down!!!\n");
        subpage = cur_subpage;
		ret = ttx_request_sub_page_down(cur_page, subpage , &pCurRdCB );      
        if (ret == RET_SUCCESS)
		{
            //LIBC_PRINTF("subpage_down Success!\n");
            ttx_delete_whole();            bUpd_subpage_p26 = TRUE;
			WaitSubPage =0xffff;
			cur_page = pCurRdCB->page_id;
            cur_subpage = pCurRdCB->sub_page_id;
			if(g_ttx_pconfig_par.ttx_color_number==256)
			{
				TTX_ClearScreen(osd_ttx_xoffset,osd_ttx_yoffset+TTX_CHAR_H,osd_ttx_width,TTX_CHAR_H*24,TTX_B_BLACK);
				MEMSET(last_draw_data, 0xFF, 24*40);
			}
			parse_line(pCurRdCB,0,0,1);
			for(i=1;i<25;i++)
			{
                //LIBC_PRINTF("sub_page_down,i=%d\n",i);
				parse_line(pCurRdCB,i,0,0);
			}
            WaitPage = pCurRdCB->page_id;
            bUpd_subpage_p26 = FALSE;
            show_subpage_status();
            if(cur_subpage!=0)
                bUpdPage = TRUE;
            else
                bUpdPage = FALSE;//cloud
		}
		else
		{
            //LIBC_PRINTF("subpage_down Failure!\n");
            WaitSubPage =0xffff;
            WaitPage = pCurRdCB->page_id;
            bUpdPage = FALSE;
		}
        //LIBC_PRINTF("TTX_KEY_LEFT,WaitSubPage=%d\n",WaitSubPage); 
		goto EXIT_POINT;
	}

/*.......................color ............................*/
	else if(key == TTX_KEY_RED)
	{
		keystate= 0;
		if(cur_page != 0xffff)
		{
			//LIBTTX_PRINTF("red, pCurRdCB->page_id = %d \n",pCurRdCB->page_id);
			req_page = pCurRdCB->link_red;
			if(req_page == 0xffff)
			{
				if((g_ttx_pconfig_par.user_fast_text==TRUE) && pCurRdCB->pack24_exist == 0 && queue_tag>0)
					req_page = page_queue[0];
				else
				    goto EXIT_POINT;
			}
		}
		else
		{
			goto EXIT_POINT;
		}

	}
	else if(key == TTX_KEY_GREEN)
	{
		keystate= 0;
		if(cur_page != 0xffff)
		{
			//LIBTTX_PRINTF("green, pCurRdCB->page_id = %d \n",pCurRdCB->page_id);
			req_page = pCurRdCB->link_green;
			if(req_page == 0xffff)
			{
				if((g_ttx_pconfig_par.user_fast_text==TRUE) && pCurRdCB->pack24_exist == 0 && queue_tag>1)
					req_page = page_queue[1];
				else
				    goto EXIT_POINT;
			}
		}
		else
		{
			goto EXIT_POINT;
		}

	}
	else if(key == TTX_KEY_YELLOW)
	{
		keystate= 0;
		if(cur_page != 0xffff)
		{
			//LIBTTX_PRINTF("yellow, pCurRdCB->page_id = %d \n",pCurRdCB->page_id);
			req_page = pCurRdCB->link_yellow;
			if(req_page == 0xffff)
			{
				if((g_ttx_pconfig_par.user_fast_text==TRUE) && pCurRdCB->pack24_exist == 0 && queue_tag>2)
					req_page = page_queue[2];
				else
				    goto EXIT_POINT;
			}
		}
		else
		{
			goto EXIT_POINT;
		}
	}
	else if(key == TTX_KEY_CYAN)
	{
		keystate= 0;
		if(cur_page != 0xffff)
		{
			//LIBTTX_PRINTF("cyan, pCurRdCB->page_id = %d \n",pCurRdCB->page_id);
			req_page = pCurRdCB->link_cyan;
			if(req_page == 0xffff)
			{
				if((g_ttx_pconfig_par.user_fast_text==TRUE) && pCurRdCB->pack24_exist == 0 && queue_tag>3)
					req_page = page_queue[3];
				else
				    goto EXIT_POINT;
			}		}
		else
		{
			goto EXIT_POINT;
		}
	}
	else if(key == TTX_KEY_INC1)
	{
		keystate= 0;
		if(WaitPage!=0xffff)
		{
			req_page = (WaitPage==899)?100:(WaitPage+1);
		}
		else if(cur_page != 0xffff)
		{
			req_page = (cur_page==899)?100:(cur_page+1);
		}
	}
	else if(key == TTX_KEY_DEC1)
	{
		keystate= 0;
		if(WaitPage!=0xffff)
		{
			req_page = (WaitPage==100)?899:(WaitPage-1);
		}
		else if(cur_page != 0xffff)
		{
			req_page = (cur_page==100)?899:(cur_page-1);
		}
	}
	else if(key == TTX_KEY_INC100)
	{
		keystate= 0;
		if(WaitPage!=0xffff)
		{
			req_page = (WaitPage>799)?(WaitPage-700):(WaitPage+100);
		}
		else if(cur_page != 0xffff)
		{
			req_page = (cur_page>799)?(cur_page-700):(cur_page+100);
		}
	}
	else if(key == TTX_KEY_DEC100)
	{
		keystate= 0;
		if(WaitPage!=0xffff)
		{
			req_page = (WaitPage<200)?(WaitPage+700):(WaitPage-100);
		}
		else if(cur_page != 0xffff)
		{
			req_page = (cur_page<200)?(cur_page+700):(cur_page-100);
		}
	}
	else
	{
		goto EXIT_POINT;
	}

	//LIBTTX_PRINTF("3. ttx_request_page %d \n",req_page);
	if(req_page!=0xffff)
	{
		left = 0;
		top = 0;
		g_ttx_pconfig_par.ttx_drawchar(left,top,0x01,TTX_F_WHITE,TTX_B_BLACK,0,0,'P',0);
		left = TTX_CHAR_W;
		top = 0;
		huds = (req_page/100);
		g_ttx_pconfig_par.ttx_drawchar(left,top,0x01,TTX_F_WHITE,TTX_B_BLACK,0,0,huds+0x30,0);
		left = TTX_CHAR_W*2;
		tens = (req_page-100*huds)/10;
		g_ttx_pconfig_par.ttx_drawchar(left,top,0x01,TTX_F_WHITE,TTX_B_BLACK,0,0,tens+0x30,0);
		left = TTX_CHAR_W*3;
		ones = req_page-100*huds-10*tens;
		g_ttx_pconfig_par.ttx_drawchar(left,top,0x01,TTX_F_WHITE,TTX_B_BLACK,0,0,ones+0x30,0);

        if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
            clear_SubPageCB();

		ret = ttx_request_page(ttx_dev,req_page , &pCurRdCB );
		if (ret == RET_SUCCESS)
		{
			WaitPage =0xffff;
			cur_page = pCurRdCB->page_id;
            if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
            {
                cur_subpage = pCurRdCB->sub_page_id;
                bUpdPage = bFALSE;
            }
			parse_line(pCurRdCB,0,0,1);
			for(i=1;i<25;i++)
				parse_line(pCurRdCB,i,0,0);
            if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
            {
                //for(i=0;i<25;i++)
                set_SubPageCB(pCurRdCB->sub_page_id, pCurRdCB, 0, 24, FALSE);
            }
		}
		else
		{
			//LIBTTX_PRINTF("ttx_request_page failure!\n");
			WaitPage = req_page;
		}

        if(g_ttx_pconfig_par.ttx_sub_page==TRUE)
            show_subpage_status();
	}
EXIT_POINT:
    //LIBC_PRINTF("EXIT_POINT----\n");
    if(g_ttx_pconfig_par.user_fast_text==TRUE)
    {
        if(new_history_mode!=TRUE)
        {
        	if(last_page != 0xffff)
        	{
        		queue_inc =1;
        		for(i=0;i<queue_tag;i++)
        		{
        			if(page_queue[i] == last_page && last_page!=cur_page)
        			{
        				for(j=i;j<queue_tag;j++)
        				{
        					swap_page = page_queue[j];
        					page_queue[j] = page_queue[queue_tag-1];
        					page_queue[queue_tag-1] = swap_page;
        				}
        				queue_inc = 0;
        				break;
        			}
        		}
        		if(queue_inc != 0 && last_page!=cur_page)        		{
        			if(queue_tag == 4)
        			{
        				page_queue[0] = page_queue[1];
        				page_queue[1] = page_queue[2];
        				page_queue[2] = page_queue[3];
        				page_queue[3] = last_page;
        			}
        			else
        			{
        				page_queue[queue_tag] = last_page;
        				queue_tag++;
        			}
        		}
        	}
        }
        else
            set_packet24_new(ttx_dev, last_page);
    	if(pCurRdCB && pCurRdCB->pack24_exist == 0)
    		parse_line_ext(pCurRdCB);
     }
    LEAVE_TTX_ENG();
	return;
}
UINT8 ttx_eng_get_state2(void)      // internal use
{
    return ttx_eng_state;
}
UINT8 ttx_eng_get_state(struct vbi_device *ttx_dev)
{
    return ttx_eng_state;
}

void ttx_eng_update_init_page(struct vbi_device *ttx_dev, UINT8 num, UINT32 page_addr)
{
    memcpy((void *)(g_init_page), (void *)(page_addr), sizeof(struct t_ttx_lang)*num);
}
void ttx_eng_update_subt_page(struct vbi_device *ttx_dev, UINT8 num, UINT32 page_addr)
{
    memcpy((void *)(g_subt_page), (void *)(page_addr), sizeof(struct t_ttx_lang)*num);
    g_subt_page_num = num;
}

void ttx_eng_set_cur_language(UINT32 language)
{
    memcpy((void *)g_current_language, (void *)(language), 3);
}